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
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.
Source
Thrown at src/mono/browser/runtime/globalization-locale.ts:82
// handle non-standard or malformed locales by forwarding the locale code, e.g. "xx-u-xx"
stringToUTF16(dst, dst + 2 * localeNameOriginal.length, localeNameOriginal);
setI32(dstLength, localeNameOriginal.length);
return VoidPtrNull;
}
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}.`);
stringToUTF16(dst, dst + 2 * result.length, result);
setI32(dstLength, result.length);
return VoidPtrNull;
} catch (ex: any) {
setI32(dstLength, -1);
return stringToUTF16Ptr(ex.toString());
}
}
View on GitHub (pinned to 290d5ab72c)
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.
Example fix
// before: app runs with invariant/minimal globalization
// dotnet.withConfig({ resources: { /* no icu assets */ } })
// after: provide full ICU data asset
// <WasmIcuData Include="icudt.dat" />
// or via config:
dotnet.withConfig({
resources: { icu: [{ behavior: 'icu', name: 'icudt.dat', hash: '...' }] }
}); Defensive patterns
Strategy: validation
Validate before calling
// Before requesting a specific culture, sanity-check it resolves display names
function localeInfoResolves(locale) {
try {
const c = Intl.getCanonicalLocales(locale.replace(/_/g,'-'))[0];
const parts = c.split('-');
const region = parts.length > 1 ? parts.pop() : undefined;
const lang = new Intl.DisplayNames([c], { type: 'language' }).of(parts.join('-'));
const reg = region ? new Intl.DisplayNames([c], { type: 'region' }).of(region) : undefined;
return !!(lang || reg);
} catch { return false; }
}
if (!localeInfoResolves(requestedCulture)) { /* use fallback culture or invariant */ } Type guard
function isResolvableLocale(locale: string): boolean {
try {
return Intl.getCanonicalLocales(locale.replace(/_/g,'-')).length > 0;
} catch { return false; }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Locale or culture name is null or empty. localeName=${locale
- Locale or culture name is null or empty. localeName=${locale
- Locale info for locale=${localeName} exceeds length of ${dst
- Failed to load ICU data
- invariant globalization mode is inactive and no ICU data arc
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/49c97b2c0e403d69.
Report an issue: GitHub.