dotnet/runtime · error · Error
Failed to initialize ICU data
Error message
Failed to initialize ICU data
What it means
Thrown by loadIcuData after the native _wasm_load_icu_data call returns a falsy result. ICU data (icudt.dat) provides Unicode/globalization support (culture-aware casing, collation, calendars) to the .NET WASM runtime; without it, System.Globalization fails. The native loader rejected the bytes it was handed.
Source
Thrown at src/native/libs/Common/JavaScript/host/assets.ts:125
_ems_.HEAPU32[outSize as any >>> 2] = 0;
_ems_.HEAPU32[((outSize as any) + 4) >>> 2] = 0;
return false;
}
export function loadIcuData(bytes: Uint8Array) {
const sp = _ems_.stackSave();
try {
const ptrPtr = _ems_.stackAlloc(sizeOfPtr);
if (_ems_._posix_memalign(ptrPtr as any, 16, bytes.length)) {
throw new Error("posix_memalign failed for ICU data");
}
const ptr = _ems_.HEAPU32[ptrPtr as any >>> 2];
_ems_.HEAPU8.set(bytes, ptr >>> 0);
const result = _ems_._wasm_load_icu_data(ptr as unknown as VoidPtr);
if (!result) {
throw new Error("Failed to initialize ICU data");
}
} finally {
_ems_.stackRestore(sp);
}
}
export function installVfsFile(bytes: Uint8Array, asset: VfsAsset) {
const virtualName: string = typeof (asset.virtualPath) === "string"
? asset.virtualPath
: asset.name;
const lastSlash = virtualName.lastIndexOf("/");
let parentDirectory = (lastSlash > 0)
? virtualName.substring(0, lastSlash)
: browserVirtualAppBase;
let fileName = (lastSlash > 0)
? virtualName.substring(lastSlash + 1)
: virtualName;
if (fileName.startsWith("/")) {View on GitHub (pinned to 290d5ab72c)
Solutions
- Verify the icudt.dat is the exact file shipped with this runtime build (match git hash / SDK version).
- Check the byte length/hash of the fetched buffer against the expected asset manifest entry; re-fetch if mismatched.
- Ensure the server is not double-compressing or mis-decompressing the .dat (Content-Encoding vs raw).
- If globalization is not needed, switch the runtime to invariant globalization mode to skip ICU loading entirely.
Example fix
// before: pointing loader at an old/standalone icudt.dat URL
config.resources.icudt = [{ url: '/old/icudt.dat' }];
// after: use the file from the matching runtime publish output
config.resources.icudt = publishAssets.icudt; // same build as dotnet.native.wasm Defensive patterns
Strategy: validation
Validate before calling
// Validate the ICU bytes before loading
import { expectedIcuAssets } from './dotnet.runtime.config';
const expected = expectedIcuAssets.icudt?.[0];
if (!bytes || bytes.byteLength === 0) throw new Error('ICU bytes empty');
if (expected?.size && bytes.byteLength !== expected.size) {
throw new Error(`ICU size mismatch: got ${bytes.byteLength}, expected ${expected.size}`);
}
loadIcuData(bytes); Try / catch
try { loadIcuData(bytes); }
catch (e) {
if (/Failed to initialize ICU data/.test(String(e.message))) {
// surface a deployment hint: re-fetch the matching icudt.dat
throw new Error('ICU load failed; verify the icudt.dat matches this runtime build.', { cause: e });
}
throw e;
} Prevention
- Always source icudt.dat from the same publish output as dotnet.native.wasm.
- Prefer invariant globalization in CI/tests that do not need culture data to skip ICU loading.
- Verify fetched asset length against the runtime config manifest before handing bytes to loadIcuData.
When it happens
Trigger: Calling loadIcuData(bytes) where _wasm_load_icu_data returns 0: corrupted or truncated ICU .dat, an ICU version that does not match this runtime build, an empty/wrong byte buffer, or WASM linear-memory exhaustion at posix_memalign/load time.
Common situations: Custom host fetching icudt.dat from a stale/old URL; partial publish where icudt.dat is truncated on disk; serving the file pre-gzipped without Content-Encoding so the runtime reads compressed bytes; mixing invariant-globalization build with full-ICU data file; CDN serving a partial chunk.
Related errors
- Locale or culture name is null or empty. localeName=${locale
- Locale info for locale=${localeName} is null or empty.
- 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/966c7cf8b542928a.
Report an issue: GitHub.