withastro/astro · warning
The route "${a.route}" is defined in both "${a.component}" a
Error message
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. What it means
For server-rendered routes, validateCollisions compares dynamic patterns segment-by-segment with semantic equality: [id] and [slug] at the same position are equivalent because both match any single value. When two files yield segment-equal dynamic routes in SSR mode, only one can match, so Astro warns (domain 'router') that a dynamic SSR route cannot be defined more than once.
Source
Thrown at packages/astro/src/core/routing/create-manifest.ts:685
return;
}
// Routes have the same number of segments, can use either.
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> {View on GitHub (pinned to e294953aa8)
Solutions
- Keep exactly one file per dynamic pattern — delete or rename the duplicate
- Differentiate the routes with distinct static segments (e.g. /blog/[slug] vs /news/[id])
- If both behaviors are needed, merge into one route that branches internally on the parameter value
Example fix
# before — semantically identical in SSR src/pages/shop/[slug].astro src/pages/shop/[id].astro # after src/pages/shop/[slug].astro # keep one; merge any extra logic into it
Defensive patterns
Strategy: validation
Validate before calling
import { readdirSync } from 'node:fs';
import { join } from 'node:path';
function normalize(dir, prefix = '') {
const out = [];
for (const e of readdirSync(dir, { withFileTypes: true })) {
const seg = e.name.replace(/\.(astro|js|ts)$/, '').replace(/\[.+?\]/g, '[param]');
const p = join(dir, e.name);
if (e.isDirectory()) out.push(...normalize(p, prefix + '/' + seg));
else out.push(prefix + '/' + seg);
}
return out;
}
const all = normalize('src/pages');
const dupes = all.filter((p, i) => all.indexOf(p) !== i);
if (dupes.length) throw new Error('semantically duplicate dynamic routes: ' + dupes.join(', ')); Prevention
- Use one consistent parameter name per route position across the project
- When copying a dynamic page, change a static segment, not just the param name
- Check injected routes for patterns that differ from filesystem routes only in param names
When it happens
Trigger: Two non-prerendered routes whose patterns differ only in parameter names at the same positions — e.g. pages/blog/[slug].astro next to pages/blog/[id].astro, or [...slug] vs [...path] at the same spot — after the earlier static and prerender short-circuit checks did not return.
Common situations: Copy-pasting a dynamic page and renaming the parameter; merging route folders during a refactor; an injected admin route colliding semantically with a user route in output 'server'.
Related errors
- Invalid route ${file} — rest parameter must be a standalone
- Couldn't find component for route ${routeData.pathname}
- Unexpectedly unable to find a component instance for route $
- Invalid route ${file} — parameters must be separated
- Invalid route ${file} — brackets are unbalanced
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/fd5df7fe3435c567.
Report an issue: GitHub.