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

  1. Pass a valid BCP-47 locale string (e.g. en-US) instead of an empty value.
  2. Guard the managed caller to skip the interop when CultureInfo.Name is empty or invariant.
  3. 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

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


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)