Skip to content
Errors
FrameworkErrors
On this page

Errors

Give visitors a useful response while keeping the details you need to debug.

Expected and unexpected failures

Return res.invalid() for form validation, res.notFound() for a missing resource, or an explicit status and JSON for an API error. These are ordinary application responses.

Unexpected errors from handlers, middleware, metadata, or rendering reach Goribu's request boundary. Development shows details; production uses an error ID so visitors do not receive a raw stack trace.

Build and startup mistakes fail at build or startup. The request boundary does not hide an invalid route or configuration.

A 404 page

Add a custom page for unmatched URLs and res.notFound() responses:

src/routes/_404.jsx
import { Link } from "goribu";

export const meta = { title: "Page not found", robots: "noindex" };

// Help the visitor recover from a missing URL.
export default function NotFoundPage() {
  return (
    <main>
      <h1>Page not found</h1>
      <p>The page may have moved or no longer exists.</p>
      <Link href="/">Go home</Link>
    </main>
  );
}

A handler can pass page props with res.notFound(props). Without a custom page, Goribu supplies a built-in 404 response.

A 500 page

A production error page receives url and errorId:

src/routes/_500.jsx
export const meta = { title: "Something went wrong", robots: "noindex" };

// Share the reference ID without exposing the underlying exception.
export default function ServerErrorPage({ url, errorId }) {
  return (
    <main>
      <h1>Something went wrong</h1>
      <p>We could not load {url}.</p>
      <p>Reference: <code>{errorId}</code></p>
    </main>
  );
}

url is the pathname only, without query parameters. The same ID appears in the server log with the original error. If this page also fails, Goribu falls back to a plain-text 500 response with that ID.

Development diagnostics

Under pnpm dev, unhandled request errors return a plain-text 500 with the message and stack. Fix the original error before polishing the production error page; development intentionally exposes the cause.

Malformed supported request bodies are different. Invalid JSON or a broken multipart boundary produces a safe 400 message in both modes, without an unhandled-error ID.

Production diagnostics

Ask the visitor for the error ID and find it in Worker logs. From the app directory, use the bundled Wrangler when you need a live log stream:

Terminal
pnpm --dir node_modules/goribu exec wrangler tail

Avoid placing credentials or private request data in your own log messages. Error-page HTML is not a place to display a raw caught exception.

Common repairs

Message or symptomWhat to check
Route has no page or HTTP handlerMove a helper outside the route directory, or add a supported export.
Conflicting route shapesRemove or rename duplicate URLs, including differently named dynamic parameters.
Handler returned an invalid valueReturn a res.* result instead of a plain object or Response.
res.render() needs a default exportAdd the page or return JSON, text, or a redirect.
Body could not be parsedMatch the request's Content-Type and send valid JSON or multipart data.
D1 or KV binding is missingDeclare the resource in config and restart development or rebuild.
D1 statement was awaited without a terminalAdd .get(), .all(), .value(), or .run().
Server-only module reached browser codeImport it only from a handler or middleware.
Migration history driftedRestore applied files and add a new forward migration.
Forced prerender cannot completeRemove the incompatible handler or middleware, or use Worker rendering.

Read the full [Goribu] message: it normally identifies the file or API and the repair needed.