{"record":{"id":"60c8d24aecf70e90","repo":"remix-run/react-router","slug":"spa-mode-received-a-response-status-status-cod","errorCode":null,"errorMessage":"SPA Mode: Received a ${response.status} status code from `entry.server.tsx` while prerendering your SPA Fallback HTML file.\\n${html}","messagePattern":"SPA Mode: Received a (.+?) status code from `entry\\.server\\.tsx` while prerendering your SPA Fallback HTML file\\.\\\\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":2605,"sourceCode":"                `\\`entry.server.tsx\\` while prerendering the \\`${pathname}\\` ` +\n                `path.\\n${new TextDecoder().decode(contents)}`,\n            );\n          }\n\n          return [\n            {\n              path: pathname,\n              contents,\n            },\n          ];\n        }\n\n        // Handle document responses (html or spa)\n        let html = await response.text();\n\n        if (metadata.type === \"spa\") {\n          if (response.status !== 200) {\n            throw new Error(\n              `SPA Mode: Received a ${response.status} status code from ` +\n                `\\`entry.server.tsx\\` while prerendering your SPA Fallback HTML file.\\n` +\n                html,\n            );\n          }\n\n          if (\n            !html.includes(\"window.__reactRouterContext =\") ||\n            !html.includes(\"window.__reactRouterRouteModules =\")\n          ) {\n            throw new Error(\n              \"SPA Mode: Did you forget to include `<Scripts/>` in your root route? \" +\n                \"Your pre-rendered HTML cannot hydrate without `<Scripts />`.\",\n            );\n          }\n\n          // SPA fallback is written to root regardless of basename\n          return [","sourceCodeStart":2587,"sourceCodeEnd":2623,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/plugin.ts#L2587-L2623","documentation":"Thrown in `postProcess` when `metadata.type === \"spa\"`. In SPA mode (`ssr:false`) React Router must render a single fallback HTML file (`/__spa-fallback.html`) that the server can serve for any non-prerendered path; if `entry.server.tsx` returns anything other than 200 for that fallback render, hydration cannot work. The full HTML body is included in the error to aid diagnosis.","triggerScenarios":"`ssr:false` is set and the root render throws (e.g. an error boundary fires during SSR); `entry.server.tsx` returns a custom error `Response`; the root loader throws; `entry.server.tsx` is missing or exports a broken `handleRequest`.","commonSituations":"Switching to `ssr:false` while the root route depends on SSR-only APIs; an exception in `entry.server.tsx` that returns a 500; using a custom server entry that rejects in SPA mode; a broken root layout that throws during render.","solutions":["Run `react-router serve`/preview and request `/` to see the actual SSR error in the terminal.","Inspect `entry.server.tsx` for paths that throw or return non-200 responses unconditionally.","Ensure the root route renders without depending on SSR-only data; move dynamic logic into loaders that run after hydration.","Confirm `ssr:false` is intended — if you need SSR, remove the flag."],"exampleFix":"// before: entry.server.tsx returns 500 in SPA mode\nexport default function handle(request, { loadContext }) {\n  return new Response(\"err\", { status: 500 });\n}\n// after: delegate to the standard renderer\nimport { handleRequest } from \"@react-router/node\";\nexport default (request, loadContext) =>\n  handleRequest(request, loadContext, build);","handlingStrategy":"try-catch","validationCode":"const assertEntryServerHealthy = async (renderSpaFallback) => {\n  const res = await renderSpaFallback();\n  if (res.status !== 200) throw new Error(`entry.server returned ${res.status}`);\n};","typeGuard":null,"tryCatchPattern":"try {\n  await build(root, opts);\n} catch (e) {\n  if (/SPA Mode: Received a/.test(String(e.message))) {\n    console.error(e.message); // includes the rendered HTML\n  }\n  throw e;\n}","preventionTips":["In SPA mode, ensure the root route and `entry.server.tsx` render without SSR-only dependencies.","Don't return non-200 responses from `entry.server.tsx` for the SPA fallback.","Run a local preview to surface the underlying SSR error before pushing to CI."],"tags":["spa","ssr-false","entry-server","prerender","build"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}