{"record":{"id":"d656649e93e38eeb","repo":"vercel/next.js","slug":"specified-i18n-locales-contains-invalid-values","errorCode":null,"errorMessage":"Specified i18n.locales contains invalid values (${invalidLocales.map(String).join(', ')}), locales must be valid locale tags provided as strings e.g. \"en-US\".\nSee here for list of valid language sub-tags: http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry","messagePattern":"Specified i18n\\.locales contains invalid values \\((.+?)\\), locales must be valid locale tags provided as strings e\\.g\\. \"en-US\"\\.\nSee here for list of valid language sub-tags: http://www\\.iana\\.org/assignments/language-subtag-registry/language-subtag-registry","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/next/src/server/config.ts","lineNumber":1303,"sourceCode":"            .join(\n              '\\n'\n            )}\\n\\ndomains value must follow format { domain: 'example.fr', defaultLocale: 'fr', locales: ['fr'] }.\\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`\n        )\n      }\n    }\n\n    if (!Array.isArray(i18n.locales)) {\n      throw new Error(\n        `Specified i18n.locales must be an array of locale strings e.g. [\"en-US\", \"nl-NL\"] received ${typeof i18n.locales}.\\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`\n      )\n    }\n\n    const invalidLocales = i18n.locales.filter(\n      (locale: any) => typeof locale !== 'string'\n    )\n\n    if (invalidLocales.length > 0) {\n      throw new Error(\n        `Specified i18n.locales contains invalid values (${invalidLocales\n          .map(String)\n          .join(\n            ', '\n          )}), locales must be valid locale tags provided as strings e.g. \"en-US\".\\n` +\n          `See here for list of valid language sub-tags: http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry`\n      )\n    }\n\n    if (!i18n.locales.includes(i18n.defaultLocale)) {\n      throw new Error(\n        `Specified i18n.defaultLocale should be included in i18n.locales.\\nSee more info here: https://nextjs.org/docs/messages/invalid-i18n-config`\n      )\n    }\n\n    const normalizedLocales = new Set()\n    const duplicateLocales = new Set()\n","sourceCodeStart":1285,"sourceCodeEnd":1321,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/config.ts#L1285-L1321","documentation":"Thrown when every element of `i18n.locales` is a string but one or more are not valid BCP-47-style locale tags as far as Next's string check is concerned. The filter at config.ts:1298 only removes non-string entries; this throw at line 1302 fires for the surviving non-string values, listing them via `String()`. Note: Next does not deeply validate locale tags against the IANA registry — it only rejects non-strings — so the message's IANA link is advisory.","triggerScenarios":"Placing a number, boolean, object, or null inside `locales`, e.g. `locales: ['en-US', 123]` or `locales: ['en-US', null]`. Pure-garbage strings like `'foo-bar-baz-qux-xyz'` will NOT trigger this (they pass the `typeof === 'string'` filter).","commonSituations":"Accidentally pushing a non-string into the locales array via dynamic code; spreading a config map that yields mixed types; JSON config with a numeric locale value.","solutions":["Ensure every element of `locales` is a string locale tag.","If generating locales dynamically, filter to strings first: `locales: allLocales.filter((l) => typeof l === 'string')`.","Cross-check tags against the IANA language subtag registry for correct formatting (e.g. `en-US`, not `en_US`)."],"exampleFix":"// before\ni18n: { locales: ['en-US', 42, 'fr-FR'], defaultLocale: 'en-US' }\n// after\ni18n: { locales: ['en-US', 'fr-FR'], defaultLocale: 'en-US' }","handlingStrategy":"validation","validationCode":"const invalid = i18n.locales.filter((l: any) => typeof l !== 'string');\nif (invalid.length) throw new Error(`non-string locales: ${invalid}`);","typeGuard":"function allStrings(arr: any[]): arr is string[] {\n  return arr.every((x) => typeof x === 'string');\n}","tryCatchPattern":null,"preventionTips":["Type locales as `string[]`, not `any[]`.","When building locales dynamically, filter to strings before assigning."],"tags":["config","i18n","validation"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}