dotnet/runtime · critical · Error

posix_memalign failed for ICU data

Error message

posix_memalign failed for ICU data

What it means

Thrown by loadIcuData() (src/native/libs/Common/JavaScript/host/assets.ts:181) when _posix_memalign fails to allocate the 16-byte-aligned buffer for ICU (globalization) data. ICU data files (icudt.dat) are large, so this allocation is the one most likely to hit the heap ceiling.

Source

Thrown at src/native/libs/Common/JavaScript/host/assets.ts:186

        _ems_.HEAPU32[outDataStartPtr as any >>> 2] = assembly.ptr;
        // int64_t target
        _ems_.HEAPU32[outSize as any >>> 2] = assembly.length;
        _ems_.HEAPU32[((outSize as any) + 4) >>> 2] = 0;
        return true;
    }
    _ems_.dotnetLogger.debug(`Assembly not found: '${path}'`);
    _ems_.HEAPU32[outDataStartPtr as any >>> 2] = 0;
    _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;

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Use a smaller ICU data file (culture-specific ICU shards / hybrid globalization) to reduce the allocation size.
  2. Raise the runtime maximum WebAssembly.Memory.
  3. Avoid loading ICU if globalization is not needed (configure globalization mode/invariant culture).

Example fix

<!-- before: full ICU loaded into small-memory runtime -->

<!-- after: ship a culture-specific ICU shard -->
<ItemGroup>
  <BlazorWebAssemblyLoadAllGlobalizationData>false</BlazorWebAssemblyLoadAllGlobalizationData>
</ItemGroup>
<!-- and/or raise memory: { "memory": { "maximum": 2048 } } -->
Defensive patterns

Strategy: try-catch

Validate before calling

// pick a smaller ICU shard when memory is tight
function recommendedIcuAsset(): string {
  return useHybridGlobalization ? 'icudt_hybrid.dat' : 'icudt.dat';
}

Try / catch

try {
  await dotnetBrowserHostExports.loadIcuData(bytes);
} catch (err) {
  if (/posix_memalign failed for ICU data/.test(String((err as Error).message))) {
    // switch to a culture-specific ICU shard or raise maximum memory
  }
  throw err;
}

Prevention

When it happens

Trigger: fetchIcu() downloads the ICU asset, waits for the native module, then calls loadIcuData(bytes). Inside, posix_memalign(ptrPtr,16,bytes.length) returns non-zero because the heap cannot fit the ICU data blob.

Common situations: Loading the full icudt.dat into a runtime with too little maximum memory; shipping the wrong (too large) ICU shard for the app; a memory-constrained device whose maximum memory is capped low.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/ad396d8f5182d5cb. Report an issue: GitHub.