sveltejs/kit · error
The "${lookup.get(key)}" and "${route.id}" routes conflict w
Error message
The "${lookup.get(key)}" and "${route.id}" routes conflict with each other What it means
Two routes in src/routes normalize to the same URL pattern (same permutation of segments after removing duplicate slashes and trailing slashes). SvelteKit cannot decide which route handles that URL, so manifest creation fails at dev start or build.
Source
Thrown at packages/kit/src/core/sync/create_manifest_data/conflict.js:45
a.push(b + next);
if (!(matcher === '*' && b.endsWith('//'))) a.push(b + `<${matcher}>${next}`);
return a;
}, /** @type {string[]} */ ([]));
}
} else {
permutations = [normalized];
}
for (const permutation of permutations) {
// remove leading/trailing/duplicated slashes caused by prior
// manipulation of optional parameters and (groups)
const key = permutation
.replace(/\/{2,}/, '/')
.replace(/^\//, '')
.replace(/\/$/, '');
if (lookup.has(key)) {
throw new Error(
`The "${lookup.get(key)}" and "${route.id}" routes conflict with each other`
);
}
lookup.set(key, route.id);
}
}
}
/** @param {string} id */
function normalize_route_id(id) {
return (
id
// remove groups
.replace(/(?<=^|\/)\(.+?\)(?=$|\/)/g, '')
.replace(/\[[ux]\+([0-9a-f]+)\]/g, (_, x) =>
String.fromCodePoint(parseInt(x, 16)).replace(/\//g, '%2f')View on GitHub (pinned to 03f1687fe6)
Solutions
- Read both conflicting route ids from the error and delete or rename one
- Differentiate the patterns, e.g. add a literal prefix segment to one route
- Replace optional parameters with explicit routes or a single catch-all `[...slug]` with logic
- Check route groups — moving files between (groups) changes nothing about matching, so the duplicate remains
Example fix
// before — both match /x/about // src/routes/[category]/about/+page.svelte // src/routes/about/[page]/+page.svelte // after // src/routes/category/[name]/about/+page.svelte (add literal 'category' segment)
Defensive patterns
Strategy: validation
Validate before calling
// before starting dev/build, list route dirs and flag normalized duplicates
import { readdirSync } from 'node:fs';
const segs = readdirSync('src/routes', { recursive: true }).filter((p) => p.endsWith('+page.svelte'));
const seen = new Map();
for (const s of segs) {
const key = s.replace(/\/+page\.svelte/, '').replace(/\/+$/, '');
if (seen.has(key)) console.warn('Conflict:', seen.get(key), 'vs', s);
seen.set(key, s);
} Try / catch
try {
const manifest = await createManifestData(config);
} catch (e) {
if (String(e.message).includes('routes conflict with each other')) {
console.error('Rename one of the two conflicting routes listed in the message');
}
throw e;
} Prevention
- Avoid optional params [[x]] adjacent to static siblings that match the same URL
- Remember (group) folders do not change URL matching — check for duplicates they create
- Sketch your route table after refactors to verify uniqueness
When it happens
Trigger: Creating e.g. `src/routes/about/[page]` and `src/routes/[category]/about` that produce identical path permutations; duplicate optional-param routes like `/[[x]]` and a static `/` route both matching the same key.
Common situations: Refactoring route names and leaving an old duplicate; route groups (`(group)`) accidentally flattening two routes to the same path; optional parameters colliding with static siblings.
Related errors
- The ${route.id} and ${existing.route_id} routes must be merg
- Character escape sequence in ${id} must be lowercase
- Invalid character escape sequence in ${id}
- Hexadecimal escape sequence in ${id} must be two characters
- Avoid using `history.pushState(...)` and `history.replaceSta
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/b1a67b321041ca92.
Report an issue: GitHub.