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
- Set prefixDefaultLocale: true when you want redirectToDefaultLocale: true
- Or set both to false (no prefix, no redirect) and handle the root URL yourself
- 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
- Write middleware in TypeScript — the published I18nMiddlewareOptions union forbids this combination at compile time
- Remember the rule: redirecting to the default locale only makes sense when the default locale has a prefix (/en)
- Set both options to false when you do not want prefixes or redirects
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
- IncorrectStrategyForI18n
- MissingMiddlewareForInternationalization
- MissingIndexForInternationalizationError
- MissingLocaleError
- `Astro.session` was accessed but no session storage is…
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)