withastro/astro · error · AstroError

InvalidI18nMiddlewareConfiguration

InvalidI18nMiddlewareConfiguration

Error message

The option `redirectToDefaultLocale` can be enabled only when `prefixDefaultLocale` is also set to `true`; otherwise, redirects might cause infinite loops. Enable the option `prefixDefaultLocale` to continue to use `redirectToDefaultLocale`, or ensure both are set to `false`.

What it means

The i18n middleware factory (middleware() from astro:i18n) recreates Astro's i18n middleware with custom options. One combination is rejected up front: redirectToDefaultLocale: true together with prefixDefaultLocale: false. Without a prefixed default locale, redirecting / to the default locale would target the same URL and loop forever, so Astro throws InvalidI18nMiddlewareConfiguration instead. TypeScript blocks this combination at compile time; the runtime check catches untyped usage.

Solutions

  1. Set prefixDefaultLocale: true when you want redirectToDefaultLocale: true
  2. Or set both to false (no prefix, no redirect) and handle the root URL yourself
  3. Write middleware in TypeScript (or add // @ts-check) so the invalid combination is caught at compile time

Example fix

// before — src/middleware.ts
export const onRequest = middleware({ prefixDefaultLocale: false, redirectToDefaultLocale: true });

// after
export const onRequest = middleware({ prefixDefaultLocale: true, redirectToDefaultLocale: true });
Defensive patterns

Strategy: validation

Validate before calling

// src/middleware.ts — validate the option combination before passing it
const opts = { prefixDefaultLocale: true, redirectToDefaultLocale: true };
if (!opts.prefixDefaultLocale && (opts as any).redirectToDefaultLocale) {
	throw new Error('redirectToDefaultLocale requires prefixDefaultLocale: true');
}
export const onRequest = middleware(opts);

Prevention

When it happens

Trigger: Calling middleware({ prefixDefaultLocale: false, redirectToDefaultLocale: true }) in src/middleware.ts — exactly this option combination; JavaScript projects without type checking reaching the runtime guard.

Common situations: Moving routing options from astro.config into middleware form and flipping prefixDefaultLocale incorrectly; hand-written JS middleware bypassing the published types.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/78269821839f8fa4. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/virtual-modules/i18n.ts:402

 * });
 *
 * export const onRequest = sequence(customLogic, middleware({
 * 	prefixDefaultLocale: true,
 * 	redirectToDefaultLocale: false
 * }))
 *
 * ```
 */
export let middleware: (customOptions: I18nMiddlewareOptions) => MiddlewareHandler;

if (i18n?.routing === 'manual') {
	middleware = (customOptions) => {
		if (
			customOptions.prefixDefaultLocale === false &&
			// @ts-expect-error types do not allow this but we also check at runtime
			customOptions.redirectToDefaultLocale === true
		) {
			throw new AstroError(InvalidI18nMiddlewareConfiguration);
		}
		strategy = toRoutingStrategy(customOptions, {});
		fallbackType = toFallbackType(customOptions);
		const manifest: SSRManifest['i18n'] = {
			...i18n,
			strategy,
			domainLookupTable: {},
			fallbackType,
			fallback: i18n.fallback,
			domains: i18n.domains,
		};
		return I18nInternals.createMiddleware(manifest, base, trailingSlash, format);
	};
} else {
	middleware = noop('middleware');
}

/**

View on GitHub (pinned to 52e6c34790)