dotnet/runtime · error · Error
invariant globalization mode is inactive and no ICU data arc
Error message
invariant globalization mode is inactive and no ICU data archives are available
What it means
init_globalization throws when globalizationMode is set to a non-invariant mode (sharded, all, or custom) but no ICU data archive could be resolved, so preferredIcuAsset is null. The loader only auto-falls-back to invariant for the undefined/auto modes; an explicit sharded/all/custom request with missing ICU data is treated as a hard failure because culture APIs would be broken.
Source
Thrown at src/mono/browser/runtime/loader/icu.ts:23
import { GlobalizationMode, MonoConfig } from "../types";
import { ENVIRONMENT_IS_WEB, loaderHelpers } from "./globals";
import { mono_log_info, mono_log_debug } from "./logging";
export function init_globalization () {
loaderHelpers.preferredIcuAsset = getIcuResourceName(loaderHelpers.config);
let invariantMode = loaderHelpers.config.globalizationMode == GlobalizationMode.Invariant;
if (!invariantMode) {
if (loaderHelpers.preferredIcuAsset) {
mono_log_debug("ICU data archive(s) available, disabling invariant mode");
} else if (loaderHelpers.config.globalizationMode !== GlobalizationMode.Custom && loaderHelpers.config.globalizationMode !== GlobalizationMode.All && loaderHelpers.config.globalizationMode !== GlobalizationMode.Sharded) {
mono_log_debug("ICU data archive(s) not available, using invariant globalization mode");
invariantMode = true;
loaderHelpers.preferredIcuAsset = null;
} else {
const msg = "invariant globalization mode is inactive and no ICU data archives are available";
mono_log_error(`ERROR: ${msg}`);
throw new Error(msg);
}
}
const invariantEnv = "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT";
const env_variables = loaderHelpers.config.environmentVariables!;
if (env_variables[invariantEnv] === undefined && invariantMode) {
env_variables[invariantEnv] = "1";
}
if (env_variables["TZ"] === undefined) {
try {
// this call is relatively expensive, so we call it during download of other assets
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || null;
if (timezone) {
env_variables!["TZ"] = timezone;
}
} catch {
mono_log_info("failed to detect timezone, will fallback to UTC");
}View on GitHub (pinned to 290d5ab72c)
Solutions
- If you do not need culture data: set globalizationMode to 'invariant' (or InvariantGlobalization=true) and republish so the runtime uses the invariant fallback.
- If you need globalization: remove InvariantGlobalization, keep globalizationMode at sharded/all/custom, and verify the icudt*.dat file appears under _framework/ and is listed in the generated mono-config's resources.icu.
- For custom mode, confirm the custom ICU file is present in resources and its name matches getIcuResourceName's first-entry selection.
Example fix
// before: config globalizationMode 'sharded' but no icu asset shipped // mono-config.json "globalizationMode": "sharded" // after "globalizationMode": "invariant"
Defensive patterns
Strategy: validation
Validate before calling
// Inspect the generated mono-config before startup to confirm ICU assets exist for the requested mode.
const cfg = monoConfig; // the config object passed to the runtime
const mode = cfg.globalizationMode;
const hasIcu = Array.isArray(cfg.resources?.icu) && cfg.resources.icu.length > 0;
if ((mode === 'sharded' || mode === 'all' || mode === 'custom') && !hasIcu) {
throw new Error(`globalizationMode '${mode}' requires ICU data that is missing; use 'invariant' or ship icudt assets.`);
} Try / catch
// init_globalization runs during create(); catch and fall back to invariant.
try {
await dotnet.create();
} catch (e) {
if (String(e?.message).includes('no ICU data archives are available')) {
config.globalizationMode = 'invariant';
await dotnet.create(); // retry with invariant
} else throw e;
} Prevention
- Decide globalization needs up front: either enable InvariantGlobalization or ensure icudt assets are published.
- After publish, verify icudt*.dat exists under _framework/ and is listed in the mono config resources.icu.
- Do not mix <InvariantGlobalization>true</InvariantGlobalization> with a runtime config requesting sharded/all ICU.
When it happens
Trigger: config.globalizationMode is 'sharded', 'all', or 'custom' but config.resources.icu is empty or the expected file (icudt.dat / the sharded icudt_EFIGS.dat|icudt_CJK.dat|icudt_no_CJK.dat / a custom file) is absent, so getIcuResourceName returns null and the else-branch in init_globalization fires.
Common situations: Setting <InvariantGlobalization>true</InvariantGlobalization> in the project while a runtime config still requests sharded/all ICU; publishing with trimmed resources so icudt*.dat is stripped; a custom ICU file path that does not resolve; upgrading versions where ICU asset naming or sharding changed.
Related errors
- Locale or culture name is null or empty. localeName=${locale
- Failed to load ICU data
- Unrecognized asset behavior:${asset.behavior}, for asset ${a
- Locale info for locale=${localeName} is null or empty.
- Locale info for locale=${localeName} exceeds length of ${dst
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/f1bdcfcbc8f766de.
Report an issue: GitHub.