dotnet/runtime · error · Error
Locale or culture name is null or empty. localeName=
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 normalization via Intl.getCanonicalLocales, both localeName and cultureName resolve to falsy. The managed runtime calls this JS interop to obtain display names for a locale/culture pair, and an empty pair cannot be resolved. The exception is caught by the surrounding try block, written as dstLength=-1, and the error string is returned to managed code rather than aborting the process.
Solutions
- Pass a valid BCP-47 locale string (e.g. en-US) instead of an empty value.
- Guard the managed caller to skip the interop when CultureInfo.Name is empty or invariant.
- Ensure ICU/globalization data is loaded so the culture resolves to a non-empty name.
Example fix
// before var info = SystemJS_GetLocaleInfo(0, 0, 0, 0, ...); // after: supply real names var info = SystemJS_GetLocaleInfo(culturePtr, cultureLen, localePtr, localeLen, ...);
Defensive patterns
Strategy: validation
Validate before calling
// before calling the locale-info interop from managed code
if (string.IsNullOrEmpty(localeName) || string.IsNullOrEmpty(cultureName))
return; // skip the interop Try / catch
// the JS side already catches and forwards the error string to managed;
// on the managed side, treat a returned dstLength of -1 as a soft failure
int dstLength = ReadInt(dstLengthPtr);
if (dstLength == -1) { /* read error string, fall back to invariant name */ } Prevention
- Never pass empty locale/culture names to the interop.
- Default to CultureInfo.InvariantCulture.Name when the requested culture is empty.
- Ensure ICU/globalization data is loaded so cultures resolve to non-empty names.
When it happens
Trigger: Managed code calls the locale-info interop with null/empty strings for both locale and culture; a CultureInfo or RegionInfo with an empty name reaches the boundary; normalizeLocale returns undefined because Intl.getCanonicalLocales rejected the input.
Common situations: Invariant globalization mode combined with code that still requests locale display names; passing CurrentCulture before it is initialized; corrupt culture strings loaded from configuration.
Related errors
- Locale info for locale=
- Failed to initialize ICU data
- Failed to load ICU data
- invariant globalization mode is inactive and no ICU data…
- Locale info for locale=
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/19e33c8f72572fd0.
Report an issue: GitHub.
Appendix: 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 60108ba66e)