withastro/astro · error · AstroError

IncorrectStrategyForI18n

IncorrectStrategyForI18n

Error message

The function `${functionName}` can only be used when the `i18n.routing.strategy` is set to `"manual"`.

What it means

Astro i18n exposes several helper functions (`redirectToDefaultLocale`, `notFound`, `requestHasLocale`, `useFallback`, and `middleware`) that are only meaningful when the routing strategy is `"manual"`. When the strategy derived from config is anything else (e.g. pathname-prefix, domain-based), these exports are replaced with a `noop` that throws an `AstroError` (code `IncorrectStrategyForI18n`) naming the function. The strategy is computed by `toRoutingStrategy(routing, domains)` from `astro.config` i18n settings.

Source

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

import type { MiddlewareHandler } from '../types/public/common.js';
import type { AstroConfig, ValidRedirectStatus } from '../types/public/config.js';
import type { APIContext } from '../types/public/context.js';
import type { ClientDeserializedManifest } from '../types/public/index.js';

const { trailingSlash, site, i18n, build } = config as ClientDeserializedManifest;
const { format } = build;
const isBuild = import.meta.env.PROD;
const { defaultLocale, locales, domains, fallback, routing } = i18n!;
const base = import.meta.env.BASE_URL;

let strategy = toRoutingStrategy(routing, domains);
let fallbackType = toFallbackType(routing);

export type GetLocaleOptions = I18nInternals.GetLocaleOptions;

const noop = (method: string) =>
	function () {
		throw new AstroError({
			...IncorrectStrategyForI18n,
			message: IncorrectStrategyForI18n.message(method),
		});
	};

/**
 * @param locale A locale
 * @param path An optional path to add after the `locale`.
 * @param options Customise the generated path
 *
 * Returns a _relative_ path with passed locale.
 *
 * ## Errors
 *
 * Throws an error if the locale doesn't exist in the list of locales defined in the configuration.
 *
 * ## Examples
 *

View on GitHub (pinned to d081033d5f)

Solutions

  1. Set `i18n.routing: 'manual'` in astro.config.mjs to enable these helper functions.
  2. If you do not need manual control, stop importing/calling the throwing functions (redirectToDefaultLocale, notFound, requestHasLocale, middleware) and rely on automatic routing instead.
  3. Confirm `domains` config does not implicitly override the strategy if you intended manual.

Example fix

// before — astro.config.mjs
export default defineConfig({ i18n: { defaultLocale: 'en', locales: ['en','es'] } });
// code: import { middleware } from 'astro:i18n';

// after
export default defineConfig({ i18n: { defaultLocale: 'en', locales: ['en','es'], routing: 'manual' } });
Defensive patterns

Strategy: validation

Validate before calling

import { getRelativeLocaleUrl } from 'astro:i18n';
// Before relying on manual-only helpers, check your config:
// astro.config.mjs must have i18n.routing === 'manual'.
// At runtime you cannot read the strategy directly; guard your calls:
function requireManualRouting(config) {
  if (config.i18n?.routing !== 'manual') {
    throw new Error('Set i18n.routing to "manual" to use i18n helpers');
  }
}

Try / catch

import { redirectToDefaultLocale } from 'astro:i18n';
try {
  redirectToDefaultLocale(context);
} catch (e) {
  if (e.errorCode === 'IncorrectStrategyForI18n') {
    // Fallback: do manual redirect or skip
  } else throw e;
}

Prevention

When it happens

Trigger: Importing `redirectToDefaultLocale` from `astro:i18n` and calling it when `i18n.routing` is not `'manual'`. Importing `middleware` from `astro:i18n` and registering it in `astro.config` middleware while routing is automatic. Calling `notFound()` or `requestHasLocale(ctx)` outside manual routing.

Common situations: Following a tutorial or copying middleware code that assumes manual routing while your config uses the default automatic locale-prefix strategy. Upgrading Astro where the default strategy changed. Setting `i18n.routing: 'manual'` is required to opt into these helpers — without it the virtual module assigns the throwing noop.

Related errors


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