dotnet/runtime · error · Error
Locale info for locale=${localeName} is null or empty.
Error message
Locale info for locale=${localeName} is null or empty. What it means
After resolving LanguageName and RegionName via Intl.DisplayNames, the joined result (values joined by "##") is checked for emptiness. If both display names came back undefined/empty the function has no usable locale info to write and throws. The surrounding catch marshals the message to .NET with dstLength=-1.
Source
Thrown at src/native/libs/System.Native.Browser/native/globalization-locale.ts:63
// handle non-standard or malformed locales by forwarding the locale code, e.g. "xx-u-xx"
_ems_.dotnetBrowserUtilsExports.stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal);
_ems_.dotnetApi.setHeapI32(dstLength, localeNameOriginal.length);
return 0 as any;
}
throw error;
}
} else {
throw error;
}
}
const localeInfo = {
LanguageName: languageName,
RegionName: regionName,
};
const result = Object.values(localeInfo).join(OUTER_SEPARATOR);
if (!result)
throw new Error(`Locale info for locale=${localeName} is null or empty.`);
if (result.length > dstMaxLength)
throw new Error(`Locale info for locale=${localeName} exceeds length of ${dstMaxLength}.`);
_ems_.dotnetBrowserUtilsExports.stringToUTF16(dst, dst + 2 * result.length, result);
_ems_.dotnetApi.setHeapI32(dstLength, result.length);
return 0 as any;
} catch (ex: any) {
_ems_.dotnetApi.setHeapI32(dstLength, -1);
return _ems_.dotnetBrowserUtilsExports.stringToUTF16Ptr(ex.toString());
}
function normalizeLocale(locale: string | null) {
if (!locale)
return undefined;
try {
locale = locale.toLocaleLowerCase().replace("_", "-");
if (locale.startsWith("zh-")) {View on GitHub (pinned to 290d5ab72c)
Solutions
- Upgrade the host runtime to one with full Intl.DisplayNames data (full-icu / a modern browser).
- Use a more standard, resolvable locale/culture pair.
- Catch the marshaled error in .NET and fall back to the invariant culture.
Example fix
// before: exotic locale whose names can't be resolved
Intl.DisplayNames(["xx"], {type:"language"}).of("qaa") // -> undefined -> empty result
// after: use a resolvable, well-known culture
new CultureInfo("en-US"); Defensive patterns
Strategy: fallback
Validate before calling
function canResolveDisplayNames(locale, culture) {
try {
const lang = new Intl.DisplayNames([culture], { type: "language" }).of(locale.split("-")[0]);
return !!lang;
} catch { return false; }
} Try / catch
// .NET caller: check returned length; on -1 fall back to invariant culture
int len = GetLocaleInfo(locale, culture, ...);
if (len < 0) info = GetLocaleInfo("en-US", "en-US", ...); Prevention
- Prefer well-known culture codes for display-name resolution.
- Test globalization paths on all target browsers, not just Chromium.
- Treat locale display-name resolution as fallible with an invariant-culture fallback.
When it happens
Trigger: A locale that passes canonicalization but whose language/region Intl.DisplayNames.of() returns undefined — e.g. a locale with only a region and no resolvable language name in the requested culture, or a private-use subtag like 'qaa'.
Common situations: Rare/exotic or private-use locales; browsers or Node builds without full Intl.DisplayNames data (older Safari, Node without full-icu); a culture whose script the engine can't render display names for.
Related errors
- Locale or culture name is null or empty. localeName=${locale
- Locale info for locale=${localeName} is null or empty.
- Locale info for locale=${localeName} exceeds length of ${dst
- Locale or culture name is null or empty. localeName=${locale
- Locale info for locale=${localeName} exceeds length of ${dst
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/0b87e21b16939fbc.
Report an issue: GitHub.