withastro/astro · error · AstroError

Error generating routes

Error message

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

What it means

After merging generated redirects and your final route list, the Vercel adapter runs `normalizeRoutes` to produce the final Vercel routes manifest. If normalization fails (an error object is returned instead of routes), the adapter throws this AstroError wrapping the underlying message. It means the combined route set — your pages plus generated redirects — is not representable in Vercel's routing config.

Solutions

  1. Read the wrapped `normalized.error.message` — it identifies the specific route that failed
  2. Audit `src/pages/` bracket segments: params must match /^[a-zA-Z0-9_$]+$/ and spreads must be `[...name]`
  3. Rename or remove the conflicting redirect/page pair if the error mentions a collision
  4. Reproduce with `astro build` after each route change to catch the failing file quickly

Example fix

// before: src/pages/blog/[post-slug].astro

// after: src/pages/blog/[slug].astro
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await build();
} catch (e) {
  if (e instanceof AstroError && e.message.startsWith('Error generating routes')) {
    // audit src/pages bracket segments and redirect sources named in e.message
  }
  throw e;
}

Prevention

When it happens

Trigger: A page filename whose dynamic segments produce an invalid route pattern (e.g. `[foo-bar]`, nested spread params like `[...a].[...b]`), or routes that conflict once redirects are prepended to the list during `astro build` with the Vercel adapter.

Common situations: Renaming a page to a bracket pattern containing dashes or invalid characters; upgrading the Vercel adapter to a version with stricter route normalization; having a redirect whose source collides with an existing dynamic page route.

Related errors


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

Appendix: source

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

						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 3578d45d34)