withastro/astro · error · AstroError
MissingLocaleError
MissingLocaleError
Error message
The locale/path `${locale}` does not exist in the configured `i18n.locales`. What it means
getLocaleRelativeUrl() builds a locale-prefixed URL from your i18n config. It first resolves the passed `locale` against the configured `i18n.locales` (via peekCodePathToUse, matching either a locale code or a custom path). If nothing matches, it throws MissingLocale: the locale/path you passed does not exist in `i18n.locales`.
Solutions
- Add the locale to `i18n.locales` in astro.config if it should be supported.
- Pass one of the configured values exactly - a locale code or a custom path - matching case.
- Validate locale strings from user input against the configured locales before calling i18n URL utilities.
Example fix
// before - 'fr' is not configured (locales: ['en', 'es'])
const url = getLocaleRelativeUrl({ locale: 'fr', locales: ['en', 'es'], path: '' });
// after - enable it in astro.config
export default defineConfig({
i18n: { defaultLocale: 'en', locales: ['en', 'es', 'fr'] },
});
// or use a configured locale
const url = getLocaleRelativeUrl({ locale: 'es', locales: ['en', 'es'], path: '' }); Defensive patterns
Strategy: type-guard
Type guard
const LOCALES = ['en', 'es'] as const;
type Locale = (typeof LOCALES)[number];
function isKnownLocale(l: string): l is Locale {
return (LOCALES as readonly string[]).includes(l);
}
if (isKnownLocale(userLocale)) {
const url = getLocaleRelativeUrl({ locale: userLocale, locales: [...LOCALES], path: '' });
} Prevention
- Keep one typed LOCALES constant and derive both i18n.locales and application code from it.
- Validate locale strings from cookies, headers, or the URL against the configured list before calling i18n utilities.
- Re-check locale lists when copying i18n config between projects.
When it happens
Trigger: Calling getLocaleRelativeUrl({ locale: 'fr', ... }) when i18n.locales is ['en', 'es']; passing a custom path or code with the wrong casing ('FR' vs 'fr'); passing a locale read from a cookie or user profile without checking it against the configured list.
Common situations: A language switcher hardcoding a locale that was never enabled; locales coming from user settings or headers that are broader than the configured set; copy-pasting i18n config between projects where the locale lists differ.
Related errors
- MissingIndexForInternationalizationError
- i18nNoLocaleFoundInPath
- i18nNotEnabled
- IncorrectStrategyForI18n
- InvalidI18nMiddlewareConfiguration
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/d5abca6eb252f296.
Report an issue: GitHub.
Appendix: 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 52e6c34790)