{"record":{"id":"f2f89323c2e83027","repo":"withastro/astro","slug":"prerenderdynamicendpointpathcollide","errorCode":"PrerenderDynamicEndpointPathCollide","errorMessage":"Could not render `${pathname}` with an `undefined` param as the generated path will collide during prerendering. Prevent passing `undefined` as `params` for the endpoint's `getStaticPaths()` function, or add an additional extension to the endpoint's filename.","messagePattern":"Could not render `(.+?)` with an `undefined` param as the generated path will collide during prerendering\\. Prevent passing `undefined` as `params` for the endpoint's `getStaticPaths\\(\\)` function, or add an additional extension to the endpoint's filename\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/core/render/params-and-props.ts","lineNumber":145,"sourceCode":"\n/**\n * If we have an endpoint at `src/pages/api/[slug].ts` that's prerendered, and the `slug`\n * is `undefined`, throw an error as we can't generate the `/api` file and `/api` directory\n * at the same time. Using something like `[slug].json.ts` instead will work.\n */\nfunction validatePrerenderEndpointCollision(\n\troute: RouteData,\n\tmod: ComponentInstance,\n\tparams: Params,\n) {\n\tif (route.type === 'endpoint' && mod.getStaticPaths) {\n\t\tconst lastSegment = route.segments[route.segments.length - 1];\n\t\tconst paramValues = Object.values(params);\n\t\tconst lastParam = paramValues[paramValues.length - 1];\n\t\t// Check last segment is solely `[slug]` or `[...slug]` case (dynamic). Make sure it's not\n\t\t// `foo[slug].js` by checking segment length === 1. Also check here if that param is undefined.\n\t\tif (lastSegment.length === 1 && lastSegment[0].dynamic && lastParam === undefined) {\n\t\t\tthrow new AstroError({\n\t\t\t\t...AstroErrorData.PrerenderDynamicEndpointPathCollide,\n\t\t\t\tmessage: AstroErrorData.PrerenderDynamicEndpointPathCollide.message(route.route),\n\t\t\t\thint: AstroErrorData.PrerenderDynamicEndpointPathCollide.hint(route.component),\n\t\t\t\tlocation: {\n\t\t\t\t\tfile: route.component,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n}\n","sourceCodeStart":127,"sourceCodeEnd":156,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/core/render/params-and-props.ts#L127-L156","documentation":"When an endpoint route's last path segment is entirely dynamic (e.g. `src/pages/api/[slug].js`), the generated output filename comes solely from the param value. If `getStaticPaths()` yields `undefined` for that last param, multiple endpoints would collapse onto the same output path, so `validatePrerenderEndpointCollision` throws `PrerenderDynamicEndpointPathCollide` during rendering instead of silently overwriting files.","triggerScenarios":"`src/pages/api/[slug].js` with `getStaticPaths()` returning `[{ params: { slug: undefined } }]` or omitting the slug key entirely; a rest endpoint `[...path].js` whose last param resolves to undefined; generating extension-less endpoint outputs where the param is the only filename content.","commonSituations":"Building JSON APIs with a single dynamic segment and returning params built from optional data (value undefined when missing); migrating `[slug].json.ts` to `[slug].ts` and hitting the collision rule; params derived from CMS fields that can be null.","solutions":["Add an additional extension to the filename so the last segment is no longer solely dynamic, e.g. `src/pages/api/[slug].json.js` (params like `og-image/[...slug].png.ts` also work)","Ensure `getStaticPaths()` always provides a concrete string for the last param — filter or default undefined values away","If some entries legitimately have no value, generate them under a fixed-name route instead of a dynamic one"],"exampleFix":"# before\nsrc/pages/api/[slug].js   # getStaticPaths returns { params: { slug: undefined } }\n\n# after\nsrc/pages/api/[slug].json.js   # last segment no longer solely dynamic\n# and/or return concrete values: [{ params: { slug: 'item-1' } }]","handlingStrategy":"validation","validationCode":"// Filter undefined last params out of getStaticPaths before returning\nexport async function getStaticPaths() {\n  const items = await fetchItems();\n  return items\n    .filter((i) => i.slug !== undefined)\n    .map((i) => ({ params: { slug: i.slug } }));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer endpoint filenames with an extension inside the last segment (`[slug].json.js`, `[...slug].png.ts`)","Never emit `undefined` param values for a dynamic endpoint's final segment","Type getStaticPaths return values as `{ params: Record<string, string> }` to catch undefined at compile time"],"tags":["endpoints","prerender","getstaticpaths","dynamic-routes","build"],"backgroundTag":"prerender-path-collision","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}