dotnet/runtime · error · Error
Locale info for locale=
Error message
Locale info for locale=${localeName} is null or empty. What it means
After resolving LanguageName and RegionName through Intl.DisplayNames, the code joins them with '##'. If the resulting string is empty (both names were undefined/empty) this error fires. It means the Intl provider accepted the locale and culture but returned no display text for either component.
Solutions
- Use full-icu / a Node build with complete ICU data so Intl.DisplayNames has entries for the locale.
- Switch the culture to a well-known locale with full display-name coverage (e.g. en-US, fr-FR) to confirm the path works, then narrow down the unsupported locale.
- On the .NET side, fall back to a parent/neutral culture (e.g. 'en' instead of 'en-xxx') when display names are unavailable.
Example fix
// before: locale with no display-name data
var ci = new CultureInfo("qaa-RU");
// after: well-known locale with ICU coverage
var ci = new CultureInfo("ru-RU"); Defensive patterns
Strategy: validation
Validate before calling
// Probe Intl.DisplayNames coverage for a locale/culture before relying on it.
function hasDisplayNames(locale: string, culture: string): boolean {
try {
const lang = new Intl.DisplayNames([culture], { type: "language" }).of(locale);
return typeof lang === "string" && lang.length > 0;
} catch {
return false;
}
}
if (!hasDisplayNames(target, uiCulture)) {
target = "en"; // fallback with known coverage
} Type guard
null
Try / catch
null
Prevention
- Use full-icu / a runtime with complete ICU data for Intl.DisplayNames.
- Prefer well-known locales with broad display-name coverage for UI culture.
- Fall back to a neutral/parent culture when display names are unavailable.
- Smoke-test exotic locales in your target environment during CI.
When it happens
Trigger: Intl.DisplayNames([cultureName], {type:'region'}).of(region) and the language variant both return undefined or empty, producing an empty join. Happens with locales whose region/script the runtime's Intl data does not have display names for.
Common situations: Running on a JS engine with reduced ICU data (older Node without full-icu, embedded WebView) where DisplayNames has no data for the requested language/region; a private-use or rare locale (e.g. 'qaa-RU') that canonicalizes but has no display strings.
Related errors
- Locale or culture name is null or empty. localeName=
- Locale info for locale=
- Locale info for locale=
- Locale info for locale=
- Locale or culture name is null or empty. localeName=
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/0b87e21b16939fbc.
Report an issue: GitHub.
Appendix: 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 60108ba66e)