withastro/astro · error · AstroError

MissingLocaleError

MissingLocaleError

Error message

The locale/path `${locale}` does not exist in the configured `i18n.locales`.

What it means

`getLocaleRelativeUrl` (and related URL builders) look up the requested `locale` against the configured `i18n.locales` via `peekCodePathToUse`. If no configured locale's code/path matches the requested locale string, it throws `MissingLocaleError` because Astro cannot build a URL for a locale it was not told about.

Source

Thrown at packages/astro/src/i18n/index.ts:69

/**
 * The base URL
 */
export function getLocaleRelativeUrl({
	locale,
	base,
	locales: _locales,
	trailingSlash,
	format,
	path,
	prependWith,
	normalizeLocale = true,
	strategy = 'pathname-prefix-other-locales',
	defaultLocale,
}: GetLocaleRelativeUrl) {
	const codeToUse = peekCodePathToUse(_locales, locale);
	if (!codeToUse) {
		throw new AstroError({
			...MissingLocale,
			message: MissingLocale.message(locale),
		});
	}
	const pathsToJoin = [base, prependWith];
	const normalizedLocale = normalizeLocale ? normalizeTheLocale(codeToUse) : codeToUse;
	if (
		strategy === 'pathname-prefix-always' ||
		strategy === 'pathname-prefix-always-no-redirect' ||
		strategy === 'domains-prefix-always' ||
		strategy === 'domains-prefix-always-no-redirect'
	) {
		pathsToJoin.push(normalizedLocale);
	} else if (locale !== defaultLocale) {
		pathsToJoin.push(normalizedLocale);
	}
	pathsToJoin.push(path);

View on GitHub (pinned to d081033d5f)

Solutions

  1. Add the missing locale to `i18n.locales` in `astro.config.mjs`.
  2. Pass exactly the `locales` value from your config to the utility instead of a hand-maintained copy.
  3. If using locale objects with `codes`, ensure the requested code appears in that locale's `codes` array.
  4. Guard the call with `pathHasLocale`/a code-membership check before invoking the URL builder.

Example fix

// before
const url = getLocaleRelativeUrl({
  locale: 'fr',
  base, locales: config.locales, path: '/about',
})
// config has i18n.locales: ['en', 'es']  -> throws

// after
// astro.config.mjs: i18n: { locales: ['en', 'es', 'fr'] }
const url = getLocaleRelativeUrl({
  locale: 'fr',
  base, locales: config.locales, path: '/about',
})
Defensive patterns

Strategy: type-guard

Validate before calling

const configuredCodes = new Set(config.locales.flatMap(l => typeof l === 'string' ? [l] : l.codes));
if (!configuredCodes.has(requestedLocale)) {
  throw new Error(`Locale ${requestedLocale} not configured`);
}

Type guard

function isConfiguredLocale(locale, locales) {
  return locales.some(l =>
    typeof l === 'string' ? l === locale : l.codes.includes(locale)
  );
}

Try / catch

null

Prevention

When it happens

Trigger: Calling `getLocaleRelativeUrl({ locale: 'fr', locales: config.locales, ... })` when `'fr'` is not present in the `locales` array passed in (neither as a bare string nor inside any locale object's `codes`).

Common situations: Typing or renaming a locale code that isn't in `astro.config` i18n.locales; passing a full language tag (e.g. `'pt-BR'`) when config only lists `'pt'`; mismatch between the locales array passed to the utility and the one in config; out-of-sync locale lists after editing config.

Related errors


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