Skip to content

fs-routes: report a clear error when a page module is marked "use client" #173

Description

@k35o

Problem

A page module marked "use client" fails the build with an error thrown from inside the RSC runtime:

Error: Unexpectedly client reference export 'generateStaticParams' is called on server
    at addPagesForLeaf (file:///…/dist/rsc/assets/entries-BASeTuXL.js:22822:26)
    at async collectStaticPaths (file:///…/dist/rsc/assets/entries-BASeTuXL.js:22856:2)

addPagesForLeaf in packages/static/src/fs-routes/tree.ts guards with typeof generate !== "function", but @vitejs/plugin-rsc builds client references via registerClientReference, so the export is a function and passes the guard.

The constraint itself is fine — generateStaticParams() runs on the server at build time, so a page module has to be a Server Component. What made it hard to act on is that no frame points at a source file: on a docs site with 86 pages under a [locale] segment, I could not tell which page to fix.

Suggested fix

registerClientReference tags client references with $$typeof: Symbol.for("react.client.reference"), so a check fits right next to the existing typeof guard. To name the file, FsRouteTreeNode would need to carry filePath — it is available at node.page = file.module in nextAdapter.ts.

Resulting message:

Dynamic route "/:locale/components" ("[locale]/components/page.tsx") exports generateStaticParams()
from a module marked "use client". generateStaticParams() runs on the server at build time, so a
page module cannot be a Client Component. Move the component body into a separate "use client"
module and re-export it from the page: export { default } from "./_page";

Threading filePath through also lets the two existing tree.ts errors name the file, the way nextAdapter.ts errors already do:

- Dynamic route "/:locale/components" has no generateStaticParams() export. …
+ Dynamic route "/:locale/components" ("[locale]/components/page.tsx") has no generateStaticParams() export. …

- generateStaticParams() for "/:locale/components" is missing a value for param "locale".
+ generateStaticParams() for "/:locale/components" ("[locale]/components/page.tsx") is missing a value for param "locale".

I patched a local copy of tree.ts / nextAdapter.ts to produce the messages above; successful builds were unchanged and only the error paths differed. Happy to open a PR with tests and a note in learn/FileSystemRouting.md if you're fine with adding that field.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions