❗️ Errors in Tirne are Intentional

In Tirne, you don’t catch errors β€” you design them. The TirneError class lets you define errors with status, type, and visibility.

βœ… Think of errors as typed responses, not thrown chaos.

πŸ§ͺ Basic TirneError Example

import { TirneError } from "tirne";

throw new TirneError("Missing name", {
  status: 400,
  type: "bad_request",
  expose: true
});
status defines HTTP response code.
type defines error semantics.
expose controls whether it is shown to the client.

πŸ“‚ Full Example with Error

import { Server, TirneError } from "tirne";
import type { Route } from "tirne";

const routes: Route[] = [
  {
    method: "GET",
    path: "/",
    handler: (req) => {
      const name = new URL(req.url).searchParams.get("name");
      if (!name) {
        throw new TirneError("Missing name", {
          status: 400,
          type: "bad_request",
          expose: true,
        });
      }
      return new Response(`Hello, ${name}`);
    },
  },
];

const server = new Server(routes);

export default {
  fetch: (req: Request) => server.fetch(req),
};
No need for try/catch or use() β€” Tirne automatically handles TirneError as part of the middleware stack.

πŸ” What Happens Under the Hood?

  • Uncaught TirneError is converted into a Response
  • status and type are included in the JSON body
  • If expose is false, error message is omitted
Errors are serialized into structured JSON: { type, status, message }

πŸ”’ Use Case: Safe API Design

This model is ideal for:

  • Form validation errors
  • Auth / permission rejections
  • Data contract violations
You don't β€œhandle” errors β€” you **declare** them.