Start SSR bundle calls createServerFn before initialization with pnpm symlinked layout
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 15.1k
- Forks
- 1.9k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 143
Description
Which project does this relate to?
Start
Describe the bug
A small TanStack Start SSR app builds successfully but returns HTTP 500 on every
request when installed with pnpm's default symlinked node_modules layout. The
emitted .output/server/_ssr/ssr.mjs invokes createServerFn before its
assignment:
TypeError: createServerFn is not a function
at .output/server/_ssr/ssr.mjs:40:18
The same source and exact dependency versions return HTTP 200 when installed
with a hoisted layout. The trigger is importing a Drizzle pgTable schema into
the server-function/query graph. Removing that schema import also makes the
symlinked build work.
The divergence begins in Nitro's intermediate Vite build:
| Install | Layout | HTTP | Intermediate SSR entry | Final ssr.mjs |
|---|---|---|---|---|
pnpm install |
symlinked | 500 | 247.04 kB | 242.49 kB |
pnpm install --config.node-linker=hoisted |
hoisted | 200 | 66.89 kB | 64.72 kB |
This was independently controlled with Bun as well: Bun's isolated layout has
the same failure and its hoisted layout succeeds. Because pnpm reproduces the
failure without Bun, the behavior follows the dependency layout and appears to
be in the TanStack Start / Nitro bundling pipeline.
Complete minimal reproducer
https://github.com/astelmach20/tanstack-start-symlink-layout-repro
The repository contains no application code, credentials, or private
dependencies. A database is not required; the module fails during SSR startup
before the sample database URL can be used.
Steps to reproduce
git clone https://github.com/astelmach20/tanstack-start-symlink-layout-repro.git
cd tanstack-start-symlink-layout-repro
corepack enable
pnpm install --frozen-lockfile
pnpm build
pnpm preview
curl -i http://127.0.0.1:4173/
The build exits 0, then the request returns HTTP 500 with
createServerFn is not a function.
Hoisted control from a second clean clone:
pnpm install --frozen-lockfile --config.node-linker=hoisted
pnpm build
pnpm preview --port 4174
curl -i http://127.0.0.1:4174/
This returns HTTP 200.
Expected behavior
The generated SSR bundle should preserve module initialization order under
pnpm's supported default layout, or the build should fail instead of emitting a
bundle that cannot serve a request.
Platform
@tanstack/react-start: 1.168.28@tanstack/react-router: 1.170.18@tanstack/react-router-ssr-query: 1.167.1@tanstack/react-query: 5.101.2nitro: 3.0.260610-betavite: 8.1.5drizzle-orm: 0.45.2postgres: 3.4.9react/react-dom: 19.2.7- pnpm: 10.17.1
- Node: 23.7.0
- OS: macOS arm64; the equivalent isolated-layout failure was also observed in
a Linux serverless runtime - Bundler: Vite / Nitro (node-server preset)
Additional context
- Possibly related: #8031 and rolldown/rolldown#9993. This reproduction is much
smaller and specifically isolates dependency layout on Vite 8.1.5. - Independent package-manager controls and analysis:
https://github.com/oven-sh/bun/issues/39963#issuecomment-5370518454 - The minimal trigger is
src/schema.tsplus its import insrc/data.ts.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal reproducer and compare the symlinked and hoisted installs using the listed pnpm build and preview commands. Inspect src/schema.ts and its import in src/data.ts, then trace Nitro's intermediate Vite build into .output/server/_ssr/ssr.mjs. Done means the symlinked layout serves HTTP 200 without calling createServerFn before initialization, or the build reports a clear failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript, vite
- Domain
- backend, build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100