{"record":{"id":"19e33c8f72572fd0","repo":"dotnet/runtime","slug":"locale-or-culture-name-is-null-or-empty-localenam","errorCode":null,"errorMessage":"Locale or culture name is null or empty. localeName=${localeName}, cultureName=${cultureName}","messagePattern":"Locale or culture name is null or empty\\. localeName=(.+?), cultureName=(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/globalization-locale.ts","lineNumber":42,"sourceCode":"        return undefined;\n    }\n}\n\nexport function SystemJS_GetLocaleInfo (culture: number, cultureLength: number, locale: number, localeLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr {\n    try {\n        const localeNameOriginal = utf16ToString(<any>locale, <any>(locale + 2 * localeLength));\n        const localeName = normalizeLocale(localeNameOriginal);\n        if (!localeName && localeNameOriginal) {\n            // handle non-standard or malformed locales by forwarding the locale code\n            stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal);\n            setI32(dstLength, localeNameOriginal.length);\n            return VoidPtrNull;\n        }\n        const cultureNameOriginal = utf16ToString(<any>culture, <any>(culture + 2 * cultureLength));\n        const cultureName = normalizeLocale(cultureNameOriginal);\n\n        if (!localeName || !cultureName)\n            throw new Error(`Locale or culture name is null or empty. localeName=${localeName}, cultureName=${cultureName}`);\n\n        const localeParts = localeName.split(\"-\");\n        // cultureName can be in a form of:\n        // 1) \"language\", e.g. \"zh\"\n        // 2) \"language-region\", e.g. \"zn-CN\"\n        // 3) \"language-script-region\", e.g. \"zh-Hans-CN\"\n        // 4) \"language-script\", e.g. \"zh-Hans\" (served in the catch block below)\n        let languageName, regionName;\n        try {\n            const region = localeParts.length > 1 ? localeParts.pop() : undefined;\n            // this line might fail if form 4 from the comment above is used:\n            regionName = region ? new Intl.DisplayNames([cultureName], { type: \"region\" }).of(region) : undefined;\n            const language = localeParts.join(\"-\");\n            languageName = new Intl.DisplayNames([cultureName], { type: \"language\" }).of(language);\n        } catch (error) {\n            if (error instanceof RangeError) {\n                // if it failed from this reason then cultureName is in a form \"language-script\", without region\n                try {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/mono/browser/runtime/globalization-locale.ts#L24-L60","documentation":"Thrown by SystemJS_GetLocaleInfo() in globalization-locale.ts when, after normalizeLocale() runs, either localeName or cultureName is falsy. normalizeLocale lowercases, fixes zh- legacy codes, and runs Intl.getCanonicalLocales, returning undefined on any failure or empty input. So this error means the locale/culture passed from the .NET side could not be canonicalized into a valid BCP-47 locale AND could not be forwarded as a raw fallback. Note: the surrounding try/catch converts this into an error string returned to native (sets dstLength=-1), so it does not crash JS but signals a globalization failure to the runtime.","triggerScenarios":"The runtime requesting locale/culture info with an empty, whitespace, or malformed culture string that normalizeLocale rejects (returns undefined) while the original was also empty (so the forwarding branch is skipped). A truly empty cultureName passed by the globalization layer when invariant/empty culture was not intended.","commonSituations":"Running in invariant globalization mode where culture strings are empty and the runtime still queries locale info. A user/OS culture that resolves to an empty or non-canonical string in this browser. Browser/Intl differences (older engines) rejecting a locale that the runtime expected to work. Custom cultureName overrides that pass an invalid value.","solutions":["If you intend invariant globalization, set globalizationMode to invariant / DOTNET_GLOBALIZATION_MODE=invariant so the runtime does not request locale info.","Provide a valid culture (e.g. en-US) explicitly via application configuration / browser locale rather than relying on an empty default.","Ensure the ICU data (sharded/all) is loaded if you need real culture resolution; without ICU the runtime may pass empty culture strings.","Update the browser/runtime if a specific locale fails canonicalization in an older Intl implementation."],"exampleFix":"// before: app runs with no culture, invariant not declared\n// runtime calls SystemJS_GetLocaleInfo with empty culture -> error string returned\n\n// after: declare invariant mode or supply a culture\n// option A - invariant (no ICU needed)\n//   DOTNET_GLOBALIZATION_MODE=invariant  (or globalizationMode: 'invariant' in config)\n// option B - explicit culture with ICU\n//   set thread culture to 'en-US' in your .NET app","handlingStrategy":"fallback","validationCode":"function resolveCultureOrDefault(culture?: string | null): string {\n  if (!culture) return 'en-US'; // or use invariant mode\n  try { Intl.getCanonicalLocales(culture); return culture; }\n  catch { return 'en-US'; }\n}","typeGuard":"function isValidCulture(c: unknown): boolean {\n  if (typeof c !== 'string' || !c) return false;\n  try { Intl.getCanonicalLocales(c); return true; } catch { return false; }\n}","tryCatchPattern":"null","preventionTips":["Declare invariant globalization mode if you do not need culture data.","Supply a valid culture explicitly rather than relying on an empty default.","Ensure ICU data is loaded when real culture resolution is required."],"tags":["globalization","locale","icu","configuration"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}