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}". A static route cannot be defined more than once. What it means
Two routes in the manifest resolve to the exact same fully-static pattern (every segment static, e.g. about.astro and about/index.astro). Only one can ever match, so Astro warns (domain 'router') that the route is defined in both files and that a static route cannot be defined more than once.
Source
Thrown at packages/astro/src/core/routing/create-manifest.ts:647
a: RouteData,
b: RouteData,
_config: AstroConfig,
logger: AstroLogger,
) {
if (a.type === 'fallback' || b.type === 'fallback') {
// If either route is a fallback route, they don't collide.
// Fallbacks are always added below other routes exactly to avoid collisions.
return;
}
if (
a.route === b.route &&
a.segments.every(isStaticSegment) &&
b.segments.every(isStaticSegment)
) {
// If both routes are the same and completely static they are guaranteed to collide
// such that one of them will never be matched.
logger.warn(
'router',
`The route "${a.route}" is defined in both "${a.component}" and "${b.component}". A static route cannot be defined more than once.`,
);
logger.warn(
'router',
'A collision will result in a hard error in following versions of Astro.',
);
return;
}
if (a.prerender || b.prerender) {
// If either route is prerendered, it is impossible to know if they collide
// at this stage because it depends on the parameters returned by `getStaticPaths`.
return;
}
if (a.segments.length !== b.segments.length) {
// If the routes have different number of segments, they cannot perfectly overlapView on GitHub (pinned to e294953aa8)
Solutions
- Delete or rename one of the two colliding files/routes
- Render markdown twins through a single dynamic route ([...slug].astro with content collections) instead of a duplicate static page
- Audit integration injectRoute patterns against your filesystem routes
Example fix
# before — both normalize to /about src/pages/about.astro src/pages/about/index.astro # after src/pages/about/index.astro # keep exactly one
Defensive patterns
Strategy: validation
Validate before calling
import { readdirSync } from 'node:fs';
import { join } from 'node:path';
function patterns(dir, prefix = '') {
const out = [];
for (const e of readdirSync(dir, { withFileTypes: true })) {
const p = join(dir, e.name);
if (e.isDirectory()) out.push(...patterns(p, prefix + '/' + e.name));
else {
const base = e.name.replace(/\.(astro|md|mdx|markdown)$/, '');
const seg = base === 'index' ? '' : '/' + base;
out.push((prefix + seg) || '/');
}
}
return out;
}
const all = patterns('src/pages');
const dupes = all.filter((p, i) => all.indexOf(p) !== i);
if (dupes.length) throw new Error('duplicate routes: ' + dupes.join(', ')); Prevention
- Pick one convention for leaf pages (file.astro OR folder/index.astro) per project
- Delete the old file in the same commit when restructuring routes
- Run the duplicate-pattern check in CI before Astro turns collisions into errors
When it happens
Trigger: Files under pages/ that normalize to the same URL: foo.astro plus foo/index.astro, index.astro plus index.md in one directory, or two injected static routes with the same pattern — and neither route being a fallback route.
Common situations: Adding index.md docs beside an existing .astro page; refactoring nested folder structures without deleting old files; copy-pasting a page under a new name; injected routes from integrations duplicating filesystem routes.
Related errors
- Unexpectedly unable to find a component instance for route $
- A collision will result in a hard error in following version
- The route "${a.route}" is defined in both "${a.component}" a
- Couldn't find component for route ${routeData.pathname}
- Unexpectedly unable to find a component instance for route $
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/4b12cdf7cc94b0c7.
Report an issue: GitHub.