withastro/astro · error · AstroError

Error generating routes: ${normalized.error.message}

Error message

Error generating routes: ${normalized.error.message}

What it means

Thrown by the Vercel adapter when `normalizeRoutes()` (combining redirects + final routes) returns an `error`. This is a broader routing-consistency failure than the redirect-only check, covering conflicts between your Astro routes and Vercel's route table (duplicate paths, conflicting rewrites, invalid patterns).

Source

Thrown at packages/integrations/vercel/src/index.ts:611

						domains:
							imagesConfig.domains || _config.image.domains
								? [...(imagesConfig.domains ?? []), ...(_config.image.domains ?? [])]
								: undefined,
						remotePatterns: [...(imagesConfig.remotePatterns ?? [])],
					};
					const remotePatterns = _config.image.remotePatterns;
					for (const pattern of remotePatterns) {
						if (isAcceptedPattern(pattern)) {
							images.remotePatterns?.push(pattern);
						}
					}
				} else if (imageService) {
					images = getDefaultImageConfig(_config.image);
				}

				const normalized = normalizeRoutes([...(redirects ?? []), ...finalRoutes]);
				if (normalized.error) {
					throw new AstroError(
						`Error generating routes: ${normalized.error.message}`,
						normalized.error.link
							? `${normalized.error.action ?? 'More info'}: ${normalized.error.link}`
							: undefined,
					);
				}

				if (_routeToHeaders && _routeToHeaders.size > 0) {
					if (!normalized.routes) {
						normalized.routes = [];
					}
					if (staticHeaders) {
						const routesWithConfigHeaders = createRoutesWithStaticHeaders(_routeToHeaders, _config);
						const fileSystemRouteIndex = normalized.routes.findIndex(
							(r) => 'handle' in r && r.handle === 'filesystem',
						);
						normalized.routes.splice(fileSystemRouteIndex, 0, ...routesWithConfigHeaders);
					}

View on GitHub (pinned to d081033d5f)

Solutions

  1. Inspect `normalized.error.message` and `normalized.error.link` for the precise conflict.
  2. Eliminate duplicate or overlapping route paths across pages and redirects.
  3. Make `trailingSlash` and `build.format` consistent so normalized paths are unique.

Example fix

// before: page route /about and redirect /about -> /about/ collide
// after: remove the redirect or rename the page
export default defineConfig({
  redirects: { '/about-old': '/about/' },
});
Defensive patterns

Strategy: try-catch

Validate before calling

const normalized = normalizeRoutes([...redirects, ...routes]);
if (normalized.error) { console.error('Route conflict:', normalized.error.message); }

Type guard

function hasNormalizedError(r: unknown): r is { error: { message: string } } {
  return !!(r as any)?.error;
}

Try / catch

try { /* build */ } catch (e) { if (/Error generating routes/) { /* dedupe overlapping routes */ } else throw e; }

Prevention

When it happens

Trigger: Two routes resolving to the same normalized path. A route pattern Vercel cannot represent. Redirects colliding with page routes. Inconsistent `trailingSlash`/`build.format` producing ambiguous outputs.

Common situations: Migrating routes that overlap. Adding a redirect that targets an existing page route. Changing `build.format` ('file' vs 'directory') without updating redirects.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/c716d31730e3b6ec. Report an issue: GitHub.