dotnet/runtime · error · Error
Locale or culture name is null or empty. localeName=${locale
Error message
Locale or culture name is null or empty. localeName=${localeName}, cultureName=${cultureName} What it means
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.
Source
Thrown at src/mono/browser/runtime/globalization-locale.ts:42
return undefined;
}
}
export function SystemJS_GetLocaleInfo (culture: number, cultureLength: number, locale: number, localeLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr {
try {
const localeNameOriginal = utf16ToString(<any>locale, <any>(locale + 2 * localeLength));
const localeName = normalizeLocale(localeNameOriginal);
if (!localeName && localeNameOriginal) {
// handle non-standard or malformed locales by forwarding the locale code
stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal);
setI32(dstLength, localeNameOriginal.length);
return VoidPtrNull;
}
const cultureNameOriginal = utf16ToString(<any>culture, <any>(culture + 2 * cultureLength));
const cultureName = normalizeLocale(cultureNameOriginal);
if (!localeName || !cultureName)
throw new Error(`Locale or culture name is null or empty. localeName=${localeName}, cultureName=${cultureName}`);
const localeParts = localeName.split("-");
// cultureName can be in a form of:
// 1) "language", e.g. "zh"
// 2) "language-region", e.g. "zn-CN"
// 3) "language-script-region", e.g. "zh-Hans-CN"
// 4) "language-script", e.g. "zh-Hans" (served in the catch block below)
let languageName, regionName;
try {
const region = localeParts.length > 1 ? localeParts.pop() : undefined;
// this line might fail if form 4 from the comment above is used:
regionName = region ? new Intl.DisplayNames([cultureName], { type: "region" }).of(region) : undefined;
const language = localeParts.join("-");
languageName = new Intl.DisplayNames([cultureName], { type: "language" }).of(language);
} catch (error) {
if (error instanceof RangeError) {
// if it failed from this reason then cultureName is in a form "language-script", without region
try {View on GitHub (pinned to 290d5ab72c)
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.
Example fix
// before: app runs with no culture, invariant not declared // runtime calls SystemJS_GetLocaleInfo with empty culture -> error string returned // after: declare invariant mode or supply a culture // option A - invariant (no ICU needed) // DOTNET_GLOBALIZATION_MODE=invariant (or globalizationMode: 'invariant' in config) // option B - explicit culture with ICU // set thread culture to 'en-US' in your .NET app
Defensive patterns
Strategy: fallback
Validate before calling
function resolveCultureOrDefault(culture?: string | null): string {
if (!culture) return 'en-US'; // or use invariant mode
try { Intl.getCanonicalLocales(culture); return culture; }
catch { return 'en-US'; }
} Type guard
function isValidCulture(c: unknown): boolean {
if (typeof c !== 'string' || !c) return false;
try { Intl.getCanonicalLocales(c); return true; } catch { return false; }
} Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Locale info for locale=${localeName} is null or empty.
- Locale info for locale=${localeName} exceeds length of ${dst
- invariant globalization mode is inactive and no ICU data arc
- Locale or culture name is null or empty. localeName=${locale
- Failed to load ICU data
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/19e33c8f72572fd0.
Report an issue: GitHub.