Skip to content

SSR HMR: createStartHandler is not a function on every re-evaluation (re-occurrence of #5673, 1.167.50) #7285

Description

@rshelnutt

Re-occurrence of #5673 — same error string, same source position (default-entry/server.ts:8:15). Filing as a new issue per @schiller-manuel's request in #5673 ("please create a new issue including a complete reproducer project"). The original issue was closed, but the failure is still present on the latest @tanstack/react-start (1.167.50, 22 minor versions past @zotodev's regression report at 1.145.10).

Summary

Every SSR HMR pass throws (0, __vite_ssr_import_0__.createStartHandler) is not a function on @tanstack/react-start@1.167.50. Cold start always succeeds; the second-and-subsequent SSR pass after Vite invalidates the module graph fails. The dev server becomes unusable as soon as anything is edited until it's killed and restarted.

Identical to @Flusinerd's report in #5673 against Nitro — same error string at the same source position — so the bug isn't specific to any one SSR runner; this report adds Cloudflare workerd (@cloudflare/vite-plugin) to the list of affected runners.

Stack

[vite] (ssr) hmr update /@id/virtual:cloudflare/worker-entry, /src/lib/locale-redirect.ts?tss-serverfn-split
[vite] TypeError: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
    at /<repo>/node_modules/.pnpm/@tanstack+react-start@1.167.50_.../node_modules/@tanstack/react-start/src/default-entry/server.ts:8:15
    at Object.runInlinedModule (workers/runner-worker/index.js:214:4)
    at ModuleRunner.directRequest (workers/runner-worker/vite/module-runner:1204:59)
    at ModuleRunner.cachedRequest (workers/runner-worker/vite/module-runner:1111:73)
    at / virtual:cloudflare/worker-entry:5:1
    at Object.runInlinedModule (workers/runner-worker/index.js:214:4)
    at ModuleRunner.directRequest (workers/runner-worker/vite/module-runner:1204:59)
    at ModuleRunner.cachedRequest (workers/runner-worker/vite/module-runner:1111:73)
    at ModuleRunner.import (workers/runner-worker/vite/module-runner:1061:10)
    at HMRClient.fetchUpdate (workers/runner-worker/vite/module-runner:476:21)
[vite] Failed to reload virtual:cloudflare/worker-entry. This could be due to syntax errors or importing non-existent modules.
[vite] Internal server error: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
      at runInRunnerObject (workers/runner-worker/index.js:106:3)
      at getWorkerEntryExport (workers/runner-worker/index.js:234:17)
      at null.<anonymous> (workers/runner-worker/index.js:353:24)
      at maybeCaptureError (workers/runner-worker/index.js:50:10)

The error pinpoints default-entry/server.ts:8:15, which is createStartHandler(defaultStreamHandler). So __vite_ssr_import_0__ (the namespace from @tanstack/react-start/server) returns without createStartHandler defined on it.

Environment

  • @tanstack/react-start: 1.167.50 → resolves transitively to @tanstack/react-start-server@1.166.44 → @tanstack/start-server-core@1.167.22
  • @tanstack/react-router: 1.168.25
  • @tanstack/router-plugin: 1.167.28
  • @cloudflare/vite-plugin: 1.31.2 (workerd 1.20260424.1)
  • vite: 7.3.2
  • pnpm: 9.15.4
  • Node: 22.20.0
  • macOS Darwin 23.5.0

vite.config.ts:

plugins: [
  cloudflare({ viteEnvironment: { name: 'ssr' } }),
  svgr(),
  devtools(),
  tsconfigPaths({ projects: ['./tsconfig.json'] }),
  tailwindcss(),
  tanstackStart({ router: { routeFileIgnorePattern: '_admin' } }),
  viteReact()
]

wrangler.jsonc:

{
  "compatibility_date": "2025-09-02",
  "compatibility_flags": ["nodejs_compat"],
  "main": "@tanstack/react-start/server-entry"
}

Reproduction

  1. Boot vite dev. First request to / returns 200.
  2. touch src/lib/seo/meta.ts (any source edit, including a one-character styles.css change).
  3. Next request returns 500 with the stack above. 100% reproducible.

Root cause analysis

createStartHandler is exported through a two-level wildcard re-export chain:

  • @tanstack/react-start/server (dist/esm/server.js) → export * from "@tanstack/react-start-server"
  • @tanstack/react-start-server@1.166.44 (dist/esm/index.js) → export * from "@tanstack/start-server-core"; export { StartServer, defaultRenderHandler, defaultStreamHandler };
  • @tanstack/start-server-core@1.167.22 — direct named export of createStartHandler.

Vite's SSR transform compiles export * from '...' into a runtime call that copies enumerable own properties from the imported namespace into the current module's namespace at evaluation time. When the worker entry is invalidated by HMR and the runner re-evaluates the chain, the deeply-nested wildcard re-exports do not consistently rebind createStartHandler onto the outermost namespace — the static top-level binding __vite_ssr_import_0__.createStartHandler resolves to undefined.

This matches @Flusinerd's repro on Nitro (nitro/dist/runtime/internal/vite/dev-worker.mjs, identical error string at the same default-entry/server.ts:8:15 source position), so the bug appears to be in the re-export chain itself, not in any individual SSR runner.

Workaround that worked

Replacing the auto-generated @tanstack/react-start/server-entry with a user-owned entry that defers the import to runtime:

// src/server.ts
let cachedFetch:
  | ((req: Request, env: unknown, ctx: unknown) => Promise<Response>)
  | null = null

async function getFetch() {
  if (cachedFetch) return cachedFetch
  const mod = await import('@tanstack/react-start/server')
  cachedFetch = mod.createStartHandler(mod.defaultStreamHandler) as (
    req: Request,
    env: unknown,
    ctx: unknown
  ) => Promise<Response>
  return cachedFetch
}

if (import.meta.hot) {
  import.meta.hot.accept(() => {
    cachedFetch = null
  })
}

export default {
  async fetch(request: Request, env: unknown, ctx: unknown) {
    const fn = await getFetch()
    return await fn(request, env, ctx)
  }
}
// wrangler.jsonc
"main": "./src/server.ts"  // was "@tanstack/react-start/server-entry"

Verified across 10 HMR cycles + a Playwright-driven page load — zero recurrences. The dynamic await import(...) (resolved through __vite_ssr_dynamic_import__) materializes the namespace at call time, by which point the inner chain has finished re-evaluating, and the wildcard re-exports are complete. Static top-level destructuring is what trips the bug; deferring to a runtime call avoids it.

What didn't work

  • Clearing node_modules/.vite/ — repro on the very first HMR after a fresh boot.
  • Custom src/server.ts with the same static top-level import from @tanstack/react-start/server — same chain, same error, just relocated to user source.
  • Direct deep imports of createStartHandler from @tanstack/start-server-core and defaultStreamHandler from @tanstack/react-start-server (declared as direct deps to bypass the wildcard) — fails because start-server-core references plugin-provided virtual specifiers (#tanstack-start-entry, #tanstack-start-plugin-adapters, tanstack-start-manifest:v, tanstack-start-injected-head-scripts:v) that the tanstackStart Vite plugin only resolves when the import path flows through the official @tanstack/react-start package facade. esbuild errors out with Could not resolve "#tanstack-start-entry".
  • Downgrading — @ulrichstark's bisect in ReferenceError: Cannot access '__vite_ssr_import_2__' before initialization #5673 found 1.142.1 fixed the original report, but @zotodev confirmed regression at 1.145.10, and we're 22 minor versions past that.

Related

Activity

  1. schiller-manuel commented on Apr 29, 2026

    @schiller-manuel
    Collaborator

    cannot reproduce this with vite 8, most likely fixed by vitejs/vite@235140b2d#diff-c8bdefa8a17667f39b19528579a33e58ffb616786a5558db6ad6c9f03a7ac7af

    in future please provide a full project as a git repo that can be directly cloned and installed.

  2. rshelnutt commented on Apr 29, 2026

    @rshelnutt
    Author

    @schiller-manuel Making sure I'm aligning expectations - is the official statement here that this is a Vite issue? Or simply that a newer Vite version addresses this existing issue?

    I can certainly put in effort to rebuild a full project repo on request to share and assist in troubleshooting any bugs for your platform, though it strikes me as odd that this be considered an expected requirement. More than enough data has been shared across several tickets towards this issue, all of which stating similar configurations. Unclear why this has been closed.

  3. schiller-manuel commented on Apr 29, 2026

    @schiller-manuel
    Collaborator

    yes this is a vite that has been fixed in vite 8, it's not an issue in Start.

    my comment about the full project reproducer project was just targeted at future issues, since it helps if we can directly clone it with the correct dependencies (here especially vite 7.x) to reproduce.

  4. rshelnutt commented on Apr 29, 2026

    @rshelnutt
    Author

    @schiller-manuel I've confirmed that even with a bump to 8+, clean build, the above error still persists.

    Repro: https://github.com/rshelnutt/tanstack-start-hmr-repro

    I can make a new issue if you'd prefer.

  5. rafaelsorto commented on Apr 30, 2026

    @rafaelsorto

    I'm having the same issue with a vite clouflare project. I'm still trying to downgrade versions because I have other projects working but haven't been able to get this one working. It's a fresh install done 2 days ago. The problem happens only on routes with authentication check with beforeLoad in my case and its related to HMR as it happens when I save the files, either the one with the beforeLoad or the ones in child routes

    6:05:45 PM [vite] (client) hmr update /src/styles.css?direct, /src/routes/dashboard/index.tsx, /src/routes/dashboard/index.tsx?tsr-split=component
    6:05:45 PM [vite] (ssr) hmr update /@id/virtual:cloudflare/worker-entry, /src/functions/auth.ts?tss-serverfn-split
    [vite] TypeError: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
        at /home/rafael/Documents/Projects/svcommunity-cloudflare-monorepo/node_modules/.pnpm/@tanstack+react-start@1.167.52_react-dom@19.2.5_react@19.2.5__react@19.2.5_vite@8.0.10__e88b2dd5c47ddb7471457a754ea5ad11/node_modules/@tanstack/react-start/src/default-entry/server.ts:8:15
        at Object.runInlinedModule (workers/runner-worker/index.js:214:4)
        at ModuleRunner.directRequest (workers/runner-worker/vite/module-runner:1204:59)
        at ModuleRunner.cachedRequest (workers/runner-worker/vite/module-runner:1111:73)
    
  6. markjaylunas commented on Apr 30, 2026

    @markjaylunas

    I'm having the same issue with a vite clouflare project. I'm still trying to downgrade versions because I have other projects working but haven't been able to get this one working. It's a fresh install done 2 days ago. The problem happens only on routes with authentication check with beforeLoad in my case and its related to HMR as it happens when I save the files, either the one with the beforeLoad or the ones in child routes

    6:05:45 PM [vite] (client) hmr update /src/styles.css?direct, /src/routes/dashboard/index.tsx, /src/routes/dashboard/index.tsx?tsr-split=component
    6:05:45 PM [vite] (ssr) hmr update /@id/virtual:cloudflare/worker-entry, /src/functions/auth.ts?tss-serverfn-split
    [vite] TypeError: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
        at /home/rafael/Documents/Projects/svcommunity-cloudflare-monorepo/node_modules/.pnpm/@tanstack+react-start@1.167.52_react-dom@19.2.5_react@19.2.5__react@19.2.5_vite@8.0.10__e88b2dd5c47ddb7471457a754ea5ad11/node_modules/@tanstack/react-start/src/default-entry/server.ts:8:15
        at Object.runInlinedModule (workers/runner-worker/index.js:214:4)
        at ModuleRunner.directRequest (workers/runner-worker/vite/module-runner:1204:59)
        at ModuleRunner.cachedRequest (workers/runner-worker/vite/module-runner:1111:73)
    

    same for me, its a fresh project from April 28, 2026 (2 days ago) with @tanstack/cli@latest create. i experience the error on HMR. still have no idea on the cause

  7. rafaelsorto commented on Apr 30, 2026

    @rafaelsorto

    I did more troubleshooting to hunt down this issue and it seems it's triggered on HMR when the getRequestHeaders is used via an import import { getRequestHeaders } from '@tanstack/react-start/server'.

    The reason why I'm only getting this issue when trying to access a protected route is because I use the headers with better auth to get the authenticated user

    Here is a very small repo that has the issue

    https://github.com/rafaelsorto/reproduce-start-handler-error

    It's triggered when you save the dashboard.tsx file. Removing the headers function from the server function import clears the HMR error when saving the file. The problem is that trying to work with any route inside the protected route also triggers the same error. I have downgraded many packages without being able to actually get it to work, still trying to figure out when this issue was introduced. What I noticed is that in my other projects I'm using vite 7.

    9:48:57 AM [vite] (ssr) hmr update /@id/virtual:cloudflare/worker-entry, /src/functions/user.ts?tss-serverfn-split
    [vite] TypeError: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
        at /home/rafael/Documents/Playground/cloudflare/reproduce-start-handler-error/node_modules/.pnpm/@tanstack+react-start@1.167.52_react-dom@19.2.5_react@19.2.5__react@19.2.5_vite@8.0.10__e88b2dd5c47ddb7471457a754ea5ad11/node_modules/@tanstack/react-start/src/default-entry/server.ts:8:15
        at Object.runInlinedModule (workers/runner-worker/index.js:214:4)
        at ModuleRunner.directRequest (workers/runner-worker/vite/module-runner:1204:59)
        at ModuleRunner.cachedRequest (workers/runner-worker/vite/module-runner:1111:73)
        at /virtual:cloudflare/worker-entry:5:1
        at Object.runInlinedModule (workers/runner-worker/index.js:214:4)
        at ModuleRunner.directRequest (workers/runner-worker/vite/module-runner:1204:59)
        at ModuleRunner.cachedRequest (workers/runner-worker/vite/module-runner:1111:73)
        at ModuleRunner.import (workers/runner-worker/vite/module-runner:1061:10)
        at HMRClient.fetchUpdate (workers/runner-worker/vite/module-runner:476:21)
    [vite] Failed to reload virtual:cloudflare/worker-entry. This could be due to syntax errors or importing non-existent modules. (see errors above)
    9:48:57 AM [vite] Internal server error: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
          at runInRunnerObject (workers/runner-worker/index.js:106:3)
          at getWorkerEntryExport (workers/runner-worker/index.js:234:17)
          at null.<anonymous> (workers/runner-worker/index.js:353:24)
          at maybeCaptureError (workers/runner-worker/index.js:50:10)
    9:48:57 AM [vite] Internal server error: (0 , __vite_ssr_import_0__.createStartHandler) is not a function
          at runInRunnerObject (workers/runner-worker/index.js:106:3)
          at getWorkerEntryExport (workers/runner-worker/index.js:234:17)
          at null.<anonymous> (workers/runner-worker/index.js:353:24)
          at maybeCaptureError (workers/runner-worker/index.js:50:10) (x2)
    [Client] [vite] css hot updated: /src/styles.css
    [Client] [vite] hot updated: /src/routes/dashboard.tsx
    [Client] [vite] hot updated: /src/routes/dashboard.tsx?tsr-split=component
    [Client] %o
    
    %s
    
    %s
     { routerCode: 'BEFORE_LOAD' } The above error occurred in the <MatchInnerImpl> component. React will try to recreate this component tree from scratch using the error boundary you provided, CatchBoundaryImpl.
    [Client] Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!
    [Client] Warning: Invariant failed: expected content-type header to be set
    
  8. muhajirdev commented on Apr 30, 2026

    @muhajirdev

    same

  9. stevenlyd commented on May 1, 2026

    @stevenlyd
    Contributor

    Having same issue, using Vite 8 and cloudflare plugin.

  10. schiller-manuel commented on May 3, 2026

    @schiller-manuel
    Collaborator

    @eternalsoldiers did you see the linked PR on vite? this needs to be fixed at vite. possibly we can somewhat workaround this in start but the actual issue lies in vite's HMR

  11. rafaelsorto commented on May 3, 2026

    @rafaelsorto

    Is there no workaround for this? It's driving me crazy! I tried updating to the latest Vite, etc.

    The workaround I implemented is to dinamically import the get request headers from tanstack inside my Auth functions and it's working without issues, figure out on your project which import is breaking it and change it to dynamic import inside your function thats using it

  12. rshelnutt commented on May 3, 2026

    @rshelnutt
    Author

    All - as already stated above, @schiller-manuel positively identified the related issue and has graciously already submitted a PR to address with Vite. A workaround was provided in the OP. There are certainly several additional server configurations which would be affected by the above.

    Please ensure you have reviewed the entirety of the thread before posting. This issue is being triaged; no further confirmations are necessary at this time.

    Thanks! 🙌

  13. rshelnutt commented on May 14, 2026

    @rshelnutt
    Author

    All - confirming @schiller-manuel's PR to Vite (merged and shipped in vite@8.0.12) does resolve this. ✅

    Worth flagging that a Vite bump alone wasn't enough on my end — @cloudflare/vite-plugin bundles its own copy of Vite's module-runner, so the fix only reached my dev server after bumping that too (1.37.0, which pulls wrangler@^4.91.0).

    If you're seeing this on another runtime, check whichever package wraps your dev server for a release that picks up the Vite fix.

    Thanks again @schiller-manuel! 🙌

  14. added a commit that references this issue on Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions