sveltejs/kit · error · Error

The ${route.id} and ${existing.route_id} routes must be merg

Error message

The ${route.id} and ${existing.route_id} routes must be merged into a single function that matches the ${route.pattern} regex, but they have incompatible configs. You must either rename one of the routes, or make their configs match.

What it means

When two routes compile to the same URL-matching regex, Vercel must merge them into a single serverless function. If their hashed configs (runtime, isr settings, etc.) differ, the adapter cannot pick one and throws, telling you to rename a route or align configs.

Source

Thrown at packages/adapter-vercel/index.js:144

					}

					isr_config.set(route, {
						expiration: config.isr.expiration,
						bypassToken: config.isr.bypassToken,
						allowQuery: ['__pathname', ...(config.isr.allowQuery ?? [])],
						group: isr_config.size + 1,
						passQuery: true
					});
				}

				const hash = hash_config(config);

				// first, check there are no routes with incompatible configs that will be merged
				const pattern = route.pattern.toString();
				const existing = conflicts.get(pattern);
				if (existing) {
					if (existing.hash !== hash) {
						throw new Error(
							`The ${route.id} and ${existing.route_id} routes must be merged into a single function that matches the ${route.pattern} regex, but they have incompatible configs. You must either rename one of the routes, or make their configs match.`
						);
					}
				} else {
					conflicts.set(pattern, { hash, route_id: route.id });
				}

				// then, create a group for each config
				const id = config.split ? `${hash}-${groups.size}` : hash;
				let group = groups.get(id);
				if (!group) {
					group = { i: groups.size, config, routes: [] };
					groups.set(id, group);
				}

				group.routes.push(route);
			}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Make the configs of the conflicting routes identical (same runtime, same isr settings)
  2. Rename one of the routes (e.g. change the param name or path segment) so the patterns differ
  3. Add a distinct path segment to disambiguate the routes
  4. Use `builder` logs / the error message's route ids to locate both files and compare their exported `config`

Example fix

// before: routes/[slug]/+page.js has isr, routes/[id]/+page.js has none
// after: give both identical configs or rename one route
eexport const config = { isr: { expiration: 60 } }; // in both route files
Defensive patterns

Strategy: validation

Validate before calling

// sanity: two route ids whose regex sources collide need identical configs
const byPattern = new Map();
for (const r of routes) {
  const p = r.pattern.toString();
  if (byPattern.has(p) && hashConfig(r.config) !== byPattern.get(p)) {
    throw new Error(`Incompatible configs share pattern ${p}`);
  }
  byPattern.set(p, hashConfig(r.config));
}

Type guard

const configsCompatible = (a, b) => JSON.stringify(normalize(a)) === JSON.stringify(normalize(b));

Try / catch

try {
  await build();
} catch (err) {
  if (err.message.includes('must be merged into a single function')) {
    console.error('Align configs or rename one of the two routes named in the error.');
  }
  throw err;
}

Prevention

When it happens

Trigger: During adapt(), two routes in builder.routes produce the same `route.pattern` source string but different config hashes — e.g. `/[category]` and `/[slug]` both matching the same pattern with different isr or runtime settings.

Common situations: A dynamic route and a rest/optional route whose regexes coincide; restructuring routes so two params yield identical match patterns; one route has isr config and its regex-twin does not.

Related errors


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/0e36911a18fc53ac. Report an issue: GitHub.