{"record":{"id":"b08abf2376273f28","repo":"remix-run/react-router","slug":"unable-to-prerender-path-because-it-does-not-match","errorCode":null,"errorMessage":"Unable to prerender path because it does not match any routes: ${path}","messagePattern":"Unable to prerender path because it does not match any routes: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":3782,"sourceCode":"  return arr as unknown[] as AsyncFlatten<T>;\n}\n\ntype PrerenderMetadata = {\n  type: \"data\" | \"resource\" | \"html\" | \"spa\";\n  path: string;\n  isResourceRoute?: boolean;\n};\n\nfunction assertPrerenderPathsMatchRoutes(\n  config: ResolvedReactRouterConfig,\n  prerenderPaths: string[],\n): void {\n  let routes = createPrerenderRoutes(config.routes);\n\n  for (let path of prerenderPaths) {\n    let matches = matchRoutes(routes, `/${path}/`.replace(/^\\/\\/+/, \"/\"));\n    if (!matches) {\n      throw new Error(\n        `Unable to prerender path because it does not match any routes: ${path}`,\n      );\n    }\n  }\n}\n\nfunction getPrerenderConcurrencyConfig(\n  reactRouterConfig: ResolvedReactRouterConfig,\n): number {\n  let concurrency = 1;\n  let { prerender } = reactRouterConfig;\n  if (typeof prerender === \"object\" && \"concurrency\" in prerender) {\n    concurrency = prerender.concurrency ?? 1;\n  }\n  return concurrency;\n}\n\nfunction createDataRequest(","sourceCodeStart":3764,"sourceCodeEnd":3800,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/plugin.ts#L3764-L3800","documentation":"Thrown by `assertPrerenderPathsMatchRoutes` (also via the invariant in the prerendered-routes loop). For each string in `prerender`, React Router wraps it in slashes (`/${path}/`, collapsed) and runs `matchRoutes` against the route manifest. If no route matches, the path cannot be prerendered because there is no handler to render it, and the build aborts with the offending path.","triggerScenarios":"A `prerender` entry that has no corresponding route (typo, stale entry, route removed but `prerender` not updated); a path with parameters that doesn't match a dynamic route pattern; `prerender` paths computed from a data source out of sync with routes; wrong `basename` so matching fails.","commonSituations":"Static list of `prerender` paths that drifts as routes are renamed; generating `prerender` from a CMS whose entries include unpublished/removed slugs; trailing-slash mismatches between path and route.","solutions":["Cross-check each `prerender` entry against your `routes.ts`/`flatRoutes()` output.","For dynamic slugs, ensure the `prerender` callback only returns slugs that exist as route params.","Verify `basename` matches the path prefix you are prerendering.","Drop or fix the failing path; the error names it exactly."],"exampleFix":"// before: prerender includes a path with no route\nexport const prerender = [\"/\", \"/about\", \"/old-page\"];\n// after\nexport const prerender = [\"/\", \"/about\"];","handlingStrategy":"validation","validationCode":"import { matchRoutes } from \"react-router\";\nconst assertAllPrerenderRoutable = (routes, paths: string[]) => {\n  for (const p of paths) {\n    if (!matchRoutes(routes, `/${p}/`.replace(/^\\/\\/+/, \"/\"))) {\n      throw new Error(`prerender path has no route: ${p}`);\n    }\n  }\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate `prerender` lists from the same source as routes to avoid drift.","Verify `basename` matches the prerendered prefix.","Drop stale entries when routes are renamed/removed."],"tags":["prerender","routing","manifest","config","build"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}