Skip to content

fix(docs): stop 500s on client-side navigation into /docs - #77

Merged
letstri merged 2 commits into
mainfrom
fix/docs-serverfn-react-require
Sep 5, 2026
Merged

fix(docs): stop 500s on client-side navigation into /docs#77
letstri merged 2 commits into
mainfrom
fix/docs-serverfn-react-require

Conversation

@letstri

@letstri letstri commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Clicking Documentation from the landing page showed "Something went wrong! — Cannot read properties of undefined (reading 'path')".

What was happening

The /docs/$ loader's server function was returning 500 on every call, so data came back undefined and the route component threw on data.path. The real error was in the Vercel function log:

Error: Cannot find module 'react'
Require stack:
- /var/task/_ssr/rolldown-runtime-B4iAMlE-.mjs

Direct hits on /docs/* were fine — those pages are prerendered. Only client-side navigation, which calls _serverFn, reached the crashing module. That also explains why dev never showed it: Node resolves react from the repo's own node_modules there.

Root cause

Bisected to 64586bf. fumadocs-twoslash 3.2 → 3.3 pulled in @base-ui/react, which imports the CJS-only use-sync-external-store/shim/with-selector.

Vite's SSR pass externalises react but cannot externalise the shim — under pnpm it is only reachable through a nested node_modules — so it inlines it, leaving its internal require("react") as a runtime __require("react"). Nitro's second pass then bundles React but cannot rewrite code that was already emitted, so the call survives into .vercel/output and resolves against a node_modules that does not exist on the function.

Upstream: nitrojs/nitro#4171, rolldown/rolldown#10643. The fix PR (nitrojs/nitro#4365, experimental.cjsRequireRewrite) is still open, and the latest nitro beta does not carry it.

The fix

Declaring use-sync-external-store as a direct dependency of docs hoists it to the root node_modules, so Vite externalises it and Nitro links the require to the bundled React copy.

Alternatives tested in clean worktrees, all still broken: pinning vite back to 8.0.16, ssr.external (TanStack Start ignores it), and bumping nitro to the latest beta.

Also here

taze -r -w major across the workspace (vitest 5, pnpm 12.3.4, tsdown 0.23, fumadocs-twoslash 4, jsdom 30, lucide-react 1, @types/node 26, …), plus pnpm dedupe to collapse @trpc/server onto one copy.

TypeScript deliberately stays on ^6.0.3: under 7.0.2 rolldown-plugin-dts rejects the tsc generator and falls back to tsgo, which cannot emit declarations for the solution-style tsconfig.json. svelte-check, @sveltejs/kit and tsconfck also still want TS 5/6.

Verification

  • Built bundle contains no __require("react"); the shim now reads var React = require_react()
  • Production build served with vite preview: landing page → Documentation click renders /docs, _serverFn returns 200 (same request that 500s in production today)
  • ⌘K search — the @base-ui component that pulls in the shim — works
  • check-types 14/14, lint, format:check, tests 301/301

Worth confirming on this PR's Vercel preview before merging, since the failure only reproduces in a real Vercel function.

🤖 Generated with Claude Code

letstri and others added 2 commits September 6, 2026 00:22
…R bundle

Every client-side navigation into /docs returned 500 in production:

    Error: Cannot find module 'react'
    Require stack:
    - /var/task/_ssr/rolldown-runtime-B4iAMlE-.mjs

The route loader's server function never resolved, so its `data` was
undefined and the route component threw "Cannot read properties of
undefined (reading 'path')". Direct hits on /docs/* were unaffected
because those pages are prerendered; only the `_serverFn` call made
during client-side navigation reached the crashing module.

`use-sync-external-store` is CJS-only and reaches the graph through
`@base-ui/react`, which `fumadocs-twoslash` started depending on in 3.3.
With pnpm the package is only visible through a nested `node_modules`,
so Vite's SSR pass cannot externalise it and inlines it instead —
leaving its internal `require("react")` as a runtime `__require("react")`
even though React is external. Nitro's second pass then bundles React
but cannot rewrite code that was already emitted, so the call survives
into `.vercel/output` and resolves against a `node_modules` that does
not exist on the Vercel function.

Declaring the package as a direct dependency hoists it to the root
`node_modules`, so Vite externalises it and Nitro links the require to
the bundled React copy. The built bundle now reads `require_react()`
instead of `__require("react")`.

This is a workaround for nitrojs/nitro#4171 (rolldown/rolldown#10643) and
can be dropped once nitrojs/nitro#4365 ships `experimental.cjsRequireRewrite`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`taze -r -w major` across the workspace: vitest 5, @vitest/coverage-v8 5,
pnpm 12.3.4, tsdown 0.23, @tanstack/intent 0.3.8, @testing-library/jest-dom 7,
jsdom 30, lucide-react 1, fumadocs-twoslash 4, fumadocs 16.15.7,
@types/node 26, and assorted patch bumps. Followed by `pnpm dedupe`, which
collapses @trpc/server onto a single 11.18.0 copy — permix was resolving an
older 11.17.0 through its optional peer, and the two instances made the
tRPC middleware types structurally incompatible in the
express-trpc-react example.

TypeScript stays on ^6.0.3. Under 7.0.2 the permix build fails:
rolldown-plugin-dts rejects TS 7 with the `tsc` generator and falls back to
`tsgo`, which cannot emit declarations for the solution-style tsconfig.json
("tsgo did not generate dts file for ..."). svelte-check, @sveltejs/kit and
tsconfck also still want TS 5/6. Revisit once tsdown supports project
references with tsgo.

drizzle-orm is left alone — the registry request timed out during the run,
and the workspace intentionally tracks 1.0.0-rc rather than the 0.45.x
"latest" tag.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
permix Ready Ready Preview Sep 5, 2026 9:27pm UTC

@letstri
letstri merged commit ba806dd into main Sep 5, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant