withastro/astro · error · AstroError
PrerenderDynamicEndpointPathCollide
PrerenderDynamicEndpointPathCollide
Error message
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. What it means
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.
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
Example fix
# before
src/pages/api/[slug].js # getStaticPaths returns { params: { slug: undefined } }
# after
src/pages/api/[slug].json.js # last segment no longer solely dynamic
# and/or return concrete values: [{ params: { slug: 'item-1' } }] Defensive patterns
Strategy: validation
Validate before calling
// Filter undefined last params out of getStaticPaths before returning
export async function getStaticPaths() {
const items = await fetchItems();
return items
.filter((i) => i.slug !== undefined)
.map((i) => ({ params: { slug: i.slug } }));
} Prevention
- 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
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- Failed to get static images from the Cloudflare prerender…
- Failed to get static paths from the Cloudflare prerender…
- Failed to prerender
- getStaticPaths() ignored in dynamic page
- GetStaticPathsInvalidRouteParam
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/f2f89323c2e83027.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/render/params-and-props.ts:145
/**
* If we have an endpoint at `src/pages/api/[slug].ts` that's prerendered, and the `slug`
* is `undefined`, throw an error as we can't generate the `/api` file and `/api` directory
* at the same time. Using something like `[slug].json.ts` instead will work.
*/
function validatePrerenderEndpointCollision(
route: RouteData,
mod: ComponentInstance,
params: Params,
) {
if (route.type === 'endpoint' && mod.getStaticPaths) {
const lastSegment = route.segments[route.segments.length - 1];
const paramValues = Object.values(params);
const lastParam = paramValues[paramValues.length - 1];
// Check last segment is solely `[slug]` or `[...slug]` case (dynamic). Make sure it's not
// `foo[slug].js` by checking segment length === 1. Also check here if that param is undefined.
if (lastSegment.length === 1 && lastSegment[0].dynamic && lastParam === undefined) {
throw new AstroError({
...AstroErrorData.PrerenderDynamicEndpointPathCollide,
message: AstroErrorData.PrerenderDynamicEndpointPathCollide.message(route.route),
hint: AstroErrorData.PrerenderDynamicEndpointPathCollide.hint(route.component),
location: {
file: route.component,
},
});
}
}
}
View on GitHub (pinned to 52e6c34790)