@k8ordo/server

Troubleshooting

Common symptoms, what causes them, and how to fix them.

On this page

A Server Action’s submission gets a 403

Cause

The handler accepts a POST only when its Origin header names the host of the URL it is answering. A proxy in front that rewrites Host makes the two disagree.

Fix

Have the proxy pass the original Host on unchanged. A host that calls the handler itself builds the Request with the URL the visitor asked for.

redirect() does not take the visitor anywhere

Cause

redirect() ends by throwing, and called inside a try, the catch receives what it threw.

Fix

Call redirect() outside the try.

An error says … belongs to what answers the request, and a page is a render

Cause

A page calls cookies(), responseHeaders() or requestHeaders() while it renders, and a page cannot write the response.

Fix

To read the request’s headers or cookies, use the request the page receives. To write, move the code into a guard.ts or a Server Action.

A page shows nothing but internal error

Cause

The handler could not produce an answer, and serve() answered with a 500. That is what a Server Component throwing with no Suspense boundary above it leads to.

Fix

What was thrown is in the server’s log, on a line such as k8ordo: GET /products/1 failed. If the visitor should see something better, add an error.tsx.

Cause

secure defaults to true in cookies().set(), and a browser does not keep a Secure cookie that arrived over plain HTTP. The default is false only for localhost, 127.0.0.1 and [::1].

Fix

Serve production over HTTPS. Anywhere else you run over plain HTTP, pass secure: false to set.

An error says a cookie with sameSite "none" has to be secure

Cause

A cookie with sameSite: 'none' was given secure: false. A browser drops SameSite=None without Secure, so the write fails where it is made instead of the cookie vanishing quietly.

Fix

Leave a sameSite: 'none' cookie secure, and serve it over HTTPS.

Hydration fails, but only in production

Cause

The whole document the root layout renders is hydrated, and some CDNs rewrite HTML on the way. With web-font inlining, email obfuscation or script deferral turned on, the HTML no longer matches the tree React reconciles.

Fix

Turn that feature off. Serving fonts and scripts from your own origin, rather than linking them from another, leaves the CDN nothing to rewrite.

The paths href() takes and a page’s params are not typed

Cause

The include in tsconfig.json does not reach .k8ordo/. The name starts with a dot, so an entry naming only the directory, ".k8ordo", skips it.

Fix

List it with a glob: .k8ordo/**/*.ts.

Right after a clone, params are typed as strings

Cause

.k8ordo/ is generated and not in git, so a fresh clone does not have it yet. Without the route table, params in PageProps is typed as strings rather than as the schemas’ output.

Fix

Run vite dev or vite build once before tsc, so .k8ordo/ gets written.

The build stops with routes/ holds only page.tsx, …

Cause

Something under routes/ is not a route file name — page.ts, with the wrong extension, included.

Fix

Move components and data under a directory whose name starts with _, such as _parts/. For a page, use the .tsx extension.

An error says a params schema must validate synchronously

Cause

The paramsSchema validates asynchronously. Which route answers a URL is decided before anything renders, and that decision cannot wait.

Fix

Keep the schema to the shape of the value. Check whether the data exists in the page, and throw notFound() when it does not.

The build stops with 'server-only' cannot be imported in client build

Cause

A module that imports server-only is reached from a client component. The lines below the first are the chain of imports that got it there.

Fix

Do not import it from the client component. Read it in a Server Component and pass the values down as props.

An error says Functions cannot be passed directly to Client Components

Cause

A Server Component passes a function to a client component as a prop. Props are serialized on the way, and a function cannot be.

Fix

Pass the value the function returns, or move the function into the client component.

An error says useRoute must render inside a matched <Router>

Cause

Under the framework the browser holds no route table, since the tree comes from the server. useRoute() and useParams() have no route to read.

Fix

Pass the params the page received down to the client component as props. Read the current URL with usePathname().

k8ordo

React libraries that use Baseline features without holding back.

© 2026 k8o — MIT License

Typeset in Noto Sans JP & M PLUS 2