{"record":{"id":"d5abca6eb252f296","repo":"withastro/astro","slug":"missinglocaleerror","errorCode":"MissingLocaleError","errorMessage":"The locale/path `${locale}` does not exist in the configured `i18n.locales`.","messagePattern":"The locale/path `(.+?)` does not exist in the configured `i18n\\.locales`\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/i18n/index.ts","lineNumber":69,"sourceCode":"\n/**\n * The base URL\n */\nexport function getLocaleRelativeUrl({\n\tlocale,\n\tbase,\n\tlocales: _locales,\n\ttrailingSlash,\n\tformat,\n\tpath,\n\tprependWith,\n\tnormalizeLocale = true,\n\tstrategy = 'pathname-prefix-other-locales',\n\tdefaultLocale,\n}: GetLocaleRelativeUrl) {\n\tconst codeToUse = peekCodePathToUse(_locales, locale);\n\tif (!codeToUse) {\n\t\tthrow new AstroError({\n\t\t\t...MissingLocale,\n\t\t\tmessage: MissingLocale.message(locale),\n\t\t});\n\t}\n\tconst pathsToJoin = [base, prependWith];\n\tconst normalizedLocale = normalizeLocale ? normalizeTheLocale(codeToUse) : codeToUse;\n\tif (\n\t\tstrategy === 'pathname-prefix-always' ||\n\t\tstrategy === 'pathname-prefix-always-no-redirect' ||\n\t\tstrategy === 'domains-prefix-always' ||\n\t\tstrategy === 'domains-prefix-always-no-redirect'\n\t) {\n\t\tpathsToJoin.push(normalizedLocale);\n\t} else if (locale !== defaultLocale) {\n\t\tpathsToJoin.push(normalizedLocale);\n\t}\n\tpathsToJoin.push(path);\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/i18n/index.ts#L51-L87","documentation":"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`.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before - 'fr' is not configured (locales: ['en', 'es'])\nconst url = getLocaleRelativeUrl({ locale: 'fr', locales: ['en', 'es'], path: '' });\n\n// after - enable it in astro.config\nexport default defineConfig({\n  i18n: { defaultLocale: 'en', locales: ['en', 'es', 'fr'] },\n});\n// or use a configured locale\nconst url = getLocaleRelativeUrl({ locale: 'es', locales: ['en', 'es'], path: '' });","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"const LOCALES = ['en', 'es'] as const;\ntype Locale = (typeof LOCALES)[number];\nfunction isKnownLocale(l: string): l is Locale {\n  return (LOCALES as readonly string[]).includes(l);\n}\nif (isKnownLocale(userLocale)) {\n  const url = getLocaleRelativeUrl({ locale: userLocale, locales: [...LOCALES], path: '' });\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["i18n","localization","routing","config"],"backgroundTag":"unknown-locale","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}