{"record":{"id":"2ae316845ce2741c","repo":"remix-run/react-router","slug":"prerender-html-received-a-response-status-st","errorCode":null,"errorMessage":"Prerender (html): Received a ${response.status} status code from `entry.server.tsx` while prerendering the `${pathname}` path.\n${html}","messagePattern":"Prerender \\(html\\): Received a (.+?) status code from `entry\\.server\\.tsx` while prerendering the `(.+?)` path\\.\n(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":2659,"sourceCode":"          // A short delay causes Google to interpret the redirect as temporary.\n          // https://developers.google.com/search/docs/crawling-indexing/301-redirects#metarefresh\n          let delay = response.status === 302 ? 2 : 0;\n          let escapedLocation = escapeHtml(location ?? \"\");\n          let escapedPathname = escapeHtml(pathname);\n          html = `<!doctype html>\n<head>\n<title>Redirecting to: ${escapedLocation}</title>\n<meta http-equiv=\"refresh\" content=\"${delay};url=${escapedLocation}\">\n<meta name=\"robots\" content=\"noindex\">\n</head>\n<body>\n\t<a href=\"${escapedLocation}\">\n    Redirecting from <code>${escapedPathname}</code> to <code>${escapedLocation}</code>\n  </a>\n</body>\n</html>`;\n        } else if (response.status !== 200) {\n          throw new Error(\n            `Prerender (html): Received a ${response.status} status code from ` +\n              `\\`entry.server.tsx\\` while prerendering the \\`${pathname}\\` ` +\n              `path.\\n${html}`,\n          );\n        }\n\n        return [\n          {\n            path: `${pathname}/index.html`,\n            contents: html,\n          },\n        ];\n      },\n      logFile(outputPath, metadata) {\n        invariant(viteConfig);\n        invariant(metadata);\n        // SPA fallback logging is handled in finalize after we know the final filename\n        if (metadata.type === \"spa\") {","sourceCodeStart":2641,"sourceCodeEnd":2677,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/plugin.ts#L2641-L2677","documentation":"During HTML prerendering, React Router requests each document path from the built server. Redirect responses are handled separately (they emit a meta-refresh page), but after that branch any non-200 document response is fatal, because a static file whose content is an error page would be deployed as if it were the real page. The response HTML is appended to the message so the failing page (often the error boundary output) is visible.","triggerScenarios":"A prerendered document path where rendering throws and the framework renders an error document with a 500 status; a loader returning a non-redirect error status for that path; middleware rejecting the request; entry.server.tsx returning a custom non-200 response for that route.","commonSituations":"Prerendering marketing/blog pages whose loaders fetch a CMS that fails or 404s in CI; auth-gated routes mistakenly listed in `prerender`; a root-level middleware returning 401 for all requests without the right headers.","solutions":["Read the HTML in the error message to identify the error boundary content and underlying exception","Fix or guard the loader/middleware so the path renders 200 at build time (env vars, external API guards, cached data)","Remove intentionally-protected or erroring paths from the `prerender` config","If the redirect branch is expected, make sure the loader returns a proper 3xx redirect rather than an error page"],"exampleFix":"// before (app/routes/docs.$.tsx)\nexport async function loader({ params }: Route.LoaderArgs) {\n  let doc = await fetch(`https://cms.example.com/${params['*']}`);\n  if (!doc.ok) return new Response('missing', { status: 404 });\n  return doc.json();\n}\n\n// after — exclude missing docs from prerender\n// (react-router.config.ts)\nexport default {\n  ssr: true,\n  async prerender({ getStaticPaths }) {\n    let paths = await getStaticPaths();\n    return paths.filter(async (p) => !p.startsWith('/docs/deprecated/'));\n  },\n};","handlingStrategy":"validation","validationCode":"// Validate every prerender path against a running build before the real build\nfor (const p of PRERENDER_PATHS) {\n  const res = await fetch(`http://localhost:4173${p}`);\n  if (!res.ok && !(res.status >= 300 && res.status < 400)) {\n    console.warn(`Skipping ${p} — preview returned ${res.status}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await build();\n} catch (e) {\n  if (e instanceof Error && /^Prerender \\(html\\)/.test(e.message)) {\n    // the message embeds the error-page HTML — locate the failing loader from it\n  }\n}","preventionTips":["Keep prerender lists synchronized with routes (generate from route config where possible)","Guard loaders with try/catch + cached fallback data for build-time resilience","Run `vite preview` + a link checker before enabling prerender on large sites"],"tags":["prerender","ssg","html","build"],"backgroundTag":"prerender-response-error","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}