{"record":{"id":"49c97b2c0e403d69","repo":"dotnet/runtime","slug":"locale-info-for-locale-localename-is-null-or-em","errorCode":null,"errorMessage":"Locale info for locale=${localeName} is null or empty.","messagePattern":"Locale info for locale=(.+?) is null or empty\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/globalization-locale.ts","lineNumber":82,"sourceCode":"                        // handle non-standard or malformed locales by forwarding the locale code, e.g. \"xx-u-xx\"\n                        stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal);\n                        setI32(dstLength, localeNameOriginal.length);\n                        return VoidPtrNull;\n                    }\n                    throw error;\n                }\n            } else {\n                throw error;\n            }\n        }\n        const localeInfo = {\n            LanguageName: languageName,\n            RegionName: regionName,\n        };\n        const result = Object.values(localeInfo).join(OUTER_SEPARATOR);\n\n        if (!result)\n            throw new Error(`Locale info for locale=${localeName} is null or empty.`);\n\n        if (result.length > dstMaxLength)\n            throw new Error(`Locale info for locale=${localeName} exceeds length of ${dstMaxLength}.`);\n\n        stringToUTF16(dst, dst + 2 * result.length, result);\n        setI32(dstLength, result.length);\n        return VoidPtrNull;\n    } catch (ex: any) {\n        setI32(dstLength, -1);\n        return stringToUTF16Ptr(ex.toString());\n    }\n}\n","sourceCodeStart":64,"sourceCodeEnd":95,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/mono/browser/runtime/globalization-locale.ts#L64-L95","documentation":"Thrown by SystemJS_GetLocaleInfo after it successfully resolves the locale but Intl.DisplayNames returns empty values for both LanguageName and RegionName, producing an empty result string (joined by '##'). This is the runtime's internal bridge that converts a .NET culture/locale request into a JS-side display-name lookup, and it signals that the locale is recognized but its human-readable parts could not be produced.","triggerScenarios":"Triggered when the .NET runtime calls into JS to get locale display names (via the SystemJS_GetLocaleInfo P/Invoke) and the constructed `result = LanguageName##RegionName` is falsy. Occurs with unusual or under-specified culture strings where Intl.DisplayNames.of() returns undefined for both the language and region components.","commonSituations":"Running under a minimal ICU dataset (invariant or subsetted globalization) where the requested culture's display names are not available; using a locale like a custom/privately-registered culture; running in an older JS engine whose Intl.DisplayNames lacks coverage for the requested language.","solutions":["Ship the full ICU data for your app (set globalization mode to use the full ICU .dat) so Intl.DisplayNames has the needed entries.","Verify the culture string passed from .NET is a well-formed BCP-47 tag (e.g. 'en-US', 'zh-Hans-CN') and not a malformed/custom value.","Upgrade the host browser/engine to one with complete Intl.DisplayNames support.","If the locale is intentionally non-standard, let the runtime forward it by ensuring normalizeLocale falls into the forwarding path rather than reaching the empty-result assertion."],"exampleFix":"// before: app runs with invariant/minimal globalization\n// dotnet.withConfig({ resources: { /* no icu assets */ } })\n\n// after: provide full ICU data asset\n// <WasmIcuData Include=\"icudt.dat\" />\n// or via config:\ndotnet.withConfig({\n  resources: { icu: [{ behavior: 'icu', name: 'icudt.dat', hash: '...' }] }\n});","handlingStrategy":"validation","validationCode":"// Before requesting a specific culture, sanity-check it resolves display names\nfunction localeInfoResolves(locale) {\n  try {\n    const c = Intl.getCanonicalLocales(locale.replace(/_/g,'-'))[0];\n    const parts = c.split('-');\n    const region = parts.length > 1 ? parts.pop() : undefined;\n    const lang = new Intl.DisplayNames([c], { type: 'language' }).of(parts.join('-'));\n    const reg = region ? new Intl.DisplayNames([c], { type: 'region' }).of(region) : undefined;\n    return !!(lang || reg);\n  } catch { return false; }\n}\nif (!localeInfoResolves(requestedCulture)) { /* use fallback culture or invariant */ }","typeGuard":"function isResolvableLocale(locale: string): boolean {\n  try {\n    return Intl.getCanonicalLocales(locale.replace(/_/g,'-')).length > 0;\n  } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Ship full ICU data rather than a subset for the cultures you support.","Validate user-supplied culture strings before passing them to .NET APIs that trigger locale resolution.","Provide a fallback culture in configuration so a bad culture does not crash startup."],"tags":["globalization","icu","locale","intl"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}