{"record":{"id":"42bddb2cf447683e","repo":"remix-run/react-router","slug":"prerender-request-failed-for-prerenderpath","errorCode":null,"errorMessage":"Prerender: Request failed for ${prerenderPath}: ${response.status} ${response.statusText}","messagePattern":"Prerender: Request failed for (.+?): (.+?) (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugins/prerender.ts","lineNumber":424,"sourceCode":"            },\n          },\n        };\n      },\n    },\n    configResolved(resolvedConfig) {\n      viteConfig = resolvedConfig;\n    },\n  };\n}\n\nasync function defaultPostProcess(\n  request: Request,\n  response: Response,\n): Promise<PrerenderFile[]> {\n  const prerenderPath = new URL(request.url).pathname;\n\n  if (!response.ok) {\n    throw new Error(\n      `Prerender: Request failed for ${prerenderPath}: ${response.status} ${response.statusText}`,\n    );\n  }\n\n  return [\n    {\n      path: `${prerenderPath}/index.html`,\n      contents: await response.text(),\n    },\n  ];\n}\n\nfunction defaultHandleError(request: Request, error: Error): void {\n  const prerenderPath = new URL(request.url).pathname;\n\n  if (request.signal?.aborted) {\n    throw new Error(\n      `Prerender: Request timed out for ${prerenderPath}: ${error.message}`,","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/plugins/prerender.ts#L406-L442","documentation":"The prerender plugin ships a `defaultPostProcess` used when no custom postprocess is configured: it requests each path from a Vite preview server of your built app and rejects any non-OK response. This is the last line of defense so error pages are never written out as static HTML; unlike the framework-mode postProcess variants, it does not embed the body, only status and statusText.","triggerScenarios":"Using the prerender plugin with its default postprocess where any requested path returns 4xx/5xx from the preview server (loader throw, middleware rejection, entry.server error); a request that gets redirected into a 404; wrong casing in the requested path on a case-sensitive server.","commonSituations":"Library/tool authors embedding `@react-router/dev`'s prerender plugin; prerendering pages whose loaders fail in CI; case-sensitivity differences between macOS dev and Linux CI.","solutions":["Reproduce with `react-router-serve ./build/server/index.js` (or vite preview) and curl the exact path to see the real error","Fix the loader/middleware so the path returns 200, or drop the path from the prerender list","Provide a custom `postprocess` hook if you need different status handling (e.g. allow specific non-200s)"],"exampleFix":"// before — default postprocess rejects any non-200\nprerender({ postProcess: undefined });\n\n// after — custom postprocess that tolerates 404s\nprerender({\n  postProcess: async (request, response) => {\n    if (response.status === 404) return []; // skip, don't emit\n    return defaultPostProcess(request, response);\n  },\n});","handlingStrategy":"fallback","validationCode":"// Pre-validate all paths against a preview of the build\nconst results = await Promise.all(\n  paths.map(async (p) => [p, (await fetch(`${base}${p}`)).ok] as const),\n);\nconst goodPaths = results.filter(([, ok]) => ok).map(([p]) => p);","typeGuard":null,"tryCatchPattern":"try {\n  await prerender({ paths: goodPaths });\n} catch (e) {\n  if (e instanceof Error && /^Prerender: Request failed/.test(e.message)) {\n    // retry once, then report the failing path + status from the message\n  }\n}","preventionTips":["Smoke-test every path via `vite preview` + curl before prerendering","Supply a custom `postProcess` when some non-200s are acceptable","Watch path casing — CI on Linux is case-sensitive"],"tags":["prerender","ssg","http","build"],"backgroundTag":"prerender-request-failed","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"}