withastro/astro · warning
A collision will result in a hard error in following version
Error message
A collision will result in a hard error in following versions of Astro.
What it means
While building the route manifest, Astro detects two routes whose patterns are semantically identical (same segments, same dynamic shape) in SSR mode. Because the first matching route always wins, the second can never be reached, so Astro warns the route is defined in both components and that a collision will become a hard error in a following version. Today it is a warning; the shadowed route silently never renders.
Source
Thrown at packages/astro/src/core/routing/create-manifest.ts:689
const segmentCount = a.segments.length;
for (let index = 0; index < segmentCount; index++) {
const segmentA = a.segments[index];
const segmentB = b.segments[index];
if (!isSemanticallyEqualSegment(segmentA, segmentB)) {
// If any segment is not semantically equal between the routes
// it is not certain that the routes collide.
return;
}
}
// Both routes are guaranteed to collide such that one will never be matched.
logger.warn(
'router',
`The route "${a.route}" is defined in both "${a.component}" and "${b.component}" using SSR mode. A dynamic SSR route cannot be defined more than once.`,
);
logger.warn('router', 'A collision will result in a hard error in following versions of Astro.');
}
/**
* Create a full route manifest from filesystem and injected routes.
*/
export async function createRoutesList(
params: CreateRouteManifestParams,
logger: AstroLogger,
{
dev = false,
}: {
dev?: boolean;
} = {},
): Promise<RoutesList> {
const { settings } = params;
const { config } = settings;
// Create a map of all routes so redirects can refer to any route
const routeMap = new Map();View on GitHub (pinned to e294953aa8)
Solutions
- Look at the two components named in the warning line above — decide which route should own the pattern
- Rename or scope one route (e.g., narrow the catch-all with a prefix like /blog/[...slug])
- If an integration injects the duplicate, check its docs for configuring a different route pattern
- Fix it now: the same collision hard-errors in following Astro versions
Example fix
// before: two owners of the same SSR pattern src/pages/[...slug].astro // filesystem + integration injects '/[...slug]' // duplicate // after: only one route owns the pattern src/pages/blog/[...slug].astro // scoped
Defensive patterns
Strategy: validation
Validate before calling
// astro.config.mjs (integration) — fail the build on pattern collisions instead of warning
hooks: {
'astro:routes:resolved': ({ routes }) => {
const seen = new Map();
for (const r of routes) {
if (seen.has(r.pattern)) throw new Error(`Duplicate route ${r.pattern}: ${seen.get(r.pattern)} vs ${r.component}`);
seen.set(r.pattern, r.component);
}
},
} Prevention
- Keep exactly one catch-all route pattern; scope extras under prefixes
- When adding integrations that inject routes, grep their docs for injected patterns and deconflict
- Grep build logs for 'defined in both' in CI — a future Astro version makes it a hard error
When it happens
Trigger: A filesystem route like src/pages/[...slug].astro plus an integration-injected route with the same pattern; two injected routes whose patterns normalize to the same shape; hybrid setups where pages and custom integrations overlap.
Common situations: Adding an integration (admin panel, docs generator) that injects a catch-all over your own catch-all; upgrading Astro versions where this check was tightened; refactoring pages into injected routes without removing the originals.
Related errors
- Couldn't find component for route ${routeData.pathname}
- Unexpectedly unable to find a component instance for route $
- Astro couldn't find the correct page to render, probably bec
- Could not find server component name ${componentPath}
- Unexpectedly unable to find a component instance for route $
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/b34afcff051004be.
Report an issue: GitHub.