{"record":{"id":"d6c310af3564b745","repo":"remix-run/react-router","slug":"prerender-data-received-a-response-status-st","errorCode":null,"errorMessage":"Prerender (data): Received a ${response.status} status code from `entry.server.tsx` while prerendering the `${metadata.path}` path.\n${pathname}","messagePattern":"Prerender \\(data\\): Received a (.+?) status code from `entry\\.server\\.tsx` while prerendering the `(.+?)` path\\.\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":2554,"sourceCode":"\n        // When `ssr:false` is set, we always want a SPA HTML they can use\n        // to serve non-prerendered routes.  This file will only SSR the root\n        // route and can hydrate for any path.\n        if (!ctx.reactRouterConfig.ssr) {\n          requests.push(createSpaModeRequest(ctx.reactRouterConfig));\n        }\n\n        return requests;\n      },\n      async postProcess(request, response, metadata) {\n        invariant(metadata);\n\n        // Handle loader data responses\n        if (metadata.type === \"data\") {\n          let pathname = new URL(request.url).pathname;\n\n          if (response.status !== 200 && response.status !== 202) {\n            throw new Error(\n              `Prerender (data): Received a ${response.status} status code from ` +\n                `\\`entry.server.tsx\\` while prerendering the \\`${metadata.path}\\` ` +\n                `path.\\n${pathname}`,\n              { cause: response },\n            );\n          }\n\n          let data = await response.text();\n\n          return {\n            files: [\n              {\n                path: pathname,\n                contents: data,\n              },\n            ],\n            // After saving the .data file, request the HTML page.\n            // The data is passed along to be embedded in the response header.","sourceCodeStart":2536,"sourceCodeEnd":2572,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/plugin.ts#L2536-L2572","documentation":"During prerendering with a data strategy, React Router issues a data request against the built server and inspects the response in `postProcess`. Only 200 (success) and 202 (accepted/streamed) are allowed for `.data` requests; anything else means a loader or the server render pipeline produced an error status for a path you asked to prerender. The thrown error includes the pathname and attaches the original response as `cause` so you can inspect the body.","triggerScenarios":"A `prerender` entry whose loader throws or calls `data()`/`json()` with 4xx/5xx (e.g. a loader that 404s for missing content); an entry.server.tsx that returns a non-200 render for that path; a document redirect leaking into the data request; loaders that depend on request headers absent during prerender.","commonSituations":"Prerendering dynamic paths (`prerender: ['/blog/*']`) where some slugs legitimately 404 from the loader; loaders reading `request.headers` (host, cookie) that fall back to error responses during static generation; a root loader hitting an external API that fails during build.","solutions":["Run the failing loader locally and fix it so the prerendered path returns 200 (guard external calls, provide build-time fallback data)","Exclude paths that intentionally error from `prerender` (prune the slug list or use the `prerender` filter function to skip them)","If the path should exist, verify the route pattern matches (params spelled correctly in the file name or route config)","Inspect `error.cause` (the Response) to read the exact error body returned by the server"],"exampleFix":"// before (app/routes/blog.$slug.tsx)\nexport async function loader({ params }: Route.LoaderArgs) {\n  let post = await getPost(params.slug);\n  if (!post) throw data('Not Found', { status: 404 });\n  return { post };\n}\n\n// after — skip erroring paths at prerender time\n// (react-router.config.ts)\nexport default {\n  async prerender({ getStaticPaths }) {\n    return (await getStaticPaths()).filter(\n      (p) => !p.startsWith('/blog/drafts/')\n    );\n  },\n};","handlingStrategy":"validation","validationCode":"// react-router.config.ts — verify each prerender path succeeds before build\nexport default {\n  async prerender({ getStaticPaths }) {\n    const ok: string[] = [];\n    for (const p of await getStaticPaths()) {\n      const res = await fetch(`http://localhost:3000${p}.data`, { // local dev server\n        headers: { 'X-React-Router-Prerender': '1' },\n      });\n      if (res.ok) ok.push(p);\n    }\n    return ok;\n  },\n};","typeGuard":null,"tryCatchPattern":"try {\n  await build();\n} catch (e) {\n  if (e instanceof Error && /^Prerender \\(data\\)/.test(e.message)) {\n    // e.cause is the failed Response — read its body for the loader error\n    const body = await (e.cause as Response).text();\n    console.error('Loader failed during prerender:', body);\n  }\n}","preventionTips":["Make loaders deterministic and guarded against build-time API failures","Prune intentional 404/500 slugs from `prerender` via its filter function","Set required env vars in CI before `react-router build`"],"tags":["prerender","ssg","loader","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"}