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:
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:
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:
pnpm --dir node_modules/goribu exec wrangler tailAvoid 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 symptom | What to check |
|---|---|
| Route has no page or HTTP handler | Move a helper outside the route directory, or add a supported export. |
| Conflicting route shapes | Remove or rename duplicate URLs, including differently named dynamic parameters. |
| Handler returned an invalid value | Return a res.* result instead of a plain object or Response. |
res.render() needs a default export | Add the page or return JSON, text, or a redirect. |
| Body could not be parsed | Match the request's Content-Type and send valid JSON or multipart data. |
| D1 or KV binding is missing | Declare the resource in config and restart development or rebuild. |
| D1 statement was awaited without a terminal | Add .get(), .all(), .value(), or .run(). |
| Server-only module reached browser code | Import it only from a handler or middleware. |
| Migration history drifted | Restore applied files and add a new forward migration. |
| Forced prerender cannot complete | Remove 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.