createMiddleware is not a function on cold-start SSR in vite dev (not HMR; @tanstack/react-start@1.168.9, Vite 7.3.3)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 15.1k
- Forks
- 1.9k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 143
Description
Summary
@tanstack/react-start@1.168.9 throws (0, __vite_ssr_import_N__.createMiddleware) is not a function on the first SSR request after vite dev boots. No HMR involved — error fires on cold start, before any file edit.
Distinct from #7285 (which fails on HMR re-evaluation only, with cold start succeeding). Same root mechanism (Vite SSR module runner mishandling export * re-exports through TanStack's package facade), different surfacing.
npm run build + npm run start (prod SSR via Rollup) work correctly — Rollup statically resolves the export * chain, so the bug only surfaces in vite dev's on-demand SSR module evaluation.
Versions
@tanstack/react-start:^1.168.9@tanstack/react-router:^1.170.6@tanstack/router-plugin:^1.168.9vite:^7.3.3nitro:^3.0.260429-beta- Node:
v24.5.0 - OS: macOS (darwin 25.3.0)
Reproduction
Minimal user code triggering the bug:
// src/middlewares/auth.ts
import { createMiddleware } from "@tanstack/react-start"
export const ensureAuthenticatedMiddleware = createMiddleware().server(async ({ next }) => {
return next({ context: {} })
})
Any file in that imports this middleware will trigger the error on first SSR request.
Stack trace
TypeError: (0 , __vite_ssr_import_2__.createMiddleware) is not a function
at /<repo>/src/middlewares/auth.ts:8:46
at ESModulesEvaluator.runInlinedModule (file:///<repo>/node_modules/vite/dist/node/module-runner.js:913:3)
at ModuleRunner.directRequest (file:///<repo>/node_modules/vite/dist/node/module-runner.js:1146:59)
at ModuleRunner.cachedRequest (file:///<repo>/node_modules/vite/dist/node/module-runner.js:1053:73)
at /<repo>/src/routes/_authenticated/-serverfns/auth.ts:1:1
...
Diagnosis
createMiddleware is not a direct export of @tanstack/react-start anymore — it's re-exported transitively:
// @tanstack/react-start/dist/esm/index.js
import { useServerFn } from "./useServerFn.js";
import { createServerFn } from "@tanstack/start-client-core";
import { Hydrate } from "@tanstack/react-start-client";
export * from "@tanstack/start-client-core"; // ← createMiddleware lives here
export { Hydrate, createServerFn, useServerFn };
Plain Node ESM resolves the chain correctly:
\$ node -e "import('@tanstack/react-start').then(m => console.log(typeof m.createMiddleware))"
function
But Vite's SSR ESModulesEvaluator returns undefined for .createMiddleware on the namespace it loaded for @tanstack/react-start. The export * re-export from @tanstack/start-client-core is not being walked through to the user module.
Workaround (confirmed working)
Adding both packages to ssr.optimizeDeps.include flattens the re-export chain at optimize time (mirroring Rollup's behavior in prod):
// vite.config.ts
export default defineConfig({
plugins: [/* ... */],
ssr: {
optimizeDeps: {
include: ["@tanstack/react-start", "@tanstack/start-client-core"],
},
},
})
Cold start succeeds with this in place; full reinstall + cache clear without it does not help.
What I've ruled out
- ✅ Fresh
rm -rf node_modules && npm install - ✅ Cleared
node_modules/.vite,.vite,.nitro,.output - ✅ Bumped Vite 7.3.2 → 7.3.3
- ✅ Verified
node -e \"import('@tanstack/react-start')\"exportscreateMiddleware - ✅ Verified
dist/esm/index.jscontains theexport *re-export at runtime - ❌ Importing directly from
@tanstack/start-client-corebypasses the issue but breaks the client bundle (leaksnode:async_hooksinto browser code — thereact-startfacade is intentionally protecting against this via export conditions)
Related
- #7285 — same root cause, HMR re-evaluation surface (closed as "fix in Vite 8" but reporters confirm bug persists on Vite 8)
- #5673 — original report against Nitro
- Vite PR linked in #7285: https://github.com/vitejs/vite/commit/235140b2d
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 dist/esm/index.js and the Vite module-runner.js stack trace, then reproduce the first SSR request using the middleware in src/middlewares/auth.ts. Compare behavior with and without the ssr.optimizeDeps.include entries in vite.config.ts. Done means cold-start SSR resolves createMiddleware without the workaround while preserving the client bundle, with HMR behavior checked against #7285.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript, vite
- Domain
- backend, build-system, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100