dotnet/runtime · critical · Error
Out of memory
Error message
Out of memory
What it means
Thrown by mono_wasm_load_bytes_into_heap when the native malloc returns a non-positive pointer for the requested size (bytes.length + 16 bytes of SIMD padding). It signals the Wasm linear memory cannot satisfy the allocation, i.e. the managed/native heap is exhausted. The thrown Error is the user-visible form of an allocator failure during data marshaling into the native heap.
Solutions
- Reduce the size of the byte payload being loaded; chunk it into smaller allocations.
- Enable/grow the Wasm linear memory limit (Module.MAXIMUM_MEMORY / -s ALLOW_MEMORY_GROWTH) and confirm the runtime can grow memory.
- Audit for native heap leaks - ensure previously malloc'd buffers are freed with _free so subsequent allocations succeed.
- Stream the data instead of loading it whole into native heap.
Example fix
// before
const ptr = mono_wasm_load_bytes_into_heap(hugeBytes);
// after
const chunkSize = 1 << 20;
for (let i = 0; i < hugeBytes.length; i += chunkSize) {
const chunk = hugeBytes.subarray(i, Math.min(i + chunkSize, hugeBytes.length));
mono_wasm_load_bytes_into_heap(chunk);
} Defensive patterns
Strategy: try-catch
Validate before calling
function canAllocateHeap(bytes: Uint8Array): boolean {
// rough guard: total requested must be below half of currently free linear memory
const free = Module.HEAP8.length; // proxy for current limit
return bytes.length + 16 < free;
} Try / catch
try {
const ptr = mono_wasm_load_bytes_into_heap(bytes);
} catch (e) {
if ((e as Error).message === 'Out of memory') {
// reduce payload, grow memory, or report to user
}
throw e;
} Prevention
- Chunk large payloads into fixed-size pieces before loading into native heap.
- Free native buffers with Module._free once consumed.
- Enable ALLOW_MEMORY_GROWTH and size MAXIMUM_MEMORY to the expected peak.
When it happens
Trigger: Calling mono_wasm_load_bytes_into_heap with a very large Uint8Array when the Wasm module's linear memory is near its maximum, or when many allocations have fragmented/consumed the heap. The malloc inside the runtime returned <= 0.
Common situations: Loading large assemblies, binaries, or media blobs into native memory; running under memory-constrained devices; not growing the Wasm memory (ALLOW_MEMORY_GROWTH off) with a large dataset; a leak in native heap usage keeping prior allocations alive.
Related errors
- address must be a location in the native heap
- .NET runtime has failed to start, because too much memory…
- NotImplementedException
- Out of memory!
- Out of memory!
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/224b40a6b517ea83.
Report an issue: GitHub.
Appendix: source
Thrown at src/mono/browser/runtime/memory.ts:343
export function withStackAlloc<T1, T2, T3, TResult> (bytesWanted: number, f: (ptr: VoidPtr, ud1?: T1, ud2?: T2, ud3?: T3) => TResult, ud1?: T1, ud2?: T2, ud3?: T3): TResult {
const sp = Module.stackSave();
const ptr = Module.stackAlloc(bytesWanted);
try {
return f(ptr, ud1, ud2, ud3);
} finally {
if (loaderHelpers.is_runtime_running()) Module.stackRestore(sp);
}
}
// @bytes must be a typed array. space is allocated for it in the native heap
// and it is copied to that location. returns the address of the allocation.
export function mono_wasm_load_bytes_into_heap (bytes: Uint8Array): VoidPtr {
// pad sizes by 16 bytes for simd
const memoryOffset = malloc(bytes.length + 16);
if (<any>memoryOffset <= 0) {
mono_log_error(`malloc failed to allocate ${(bytes.length + 16)} bytes.`);
throw new Error("Out of memory");
}
const heapBytes = new Uint8Array(localHeapViewU8().buffer, <any>memoryOffset, bytes.length);
heapBytes.set(bytes);
return memoryOffset;
}
// @bytes must be a typed array. space is allocated for it in memory
// and it is copied to that location. returns the address of the data.
// the result pointer *cannot* be freed because malloc is bypassed for speed.
export function mono_wasm_load_bytes_into_heap_persistent (bytes: Uint8Array): VoidPtr {
// pad sizes by 16 bytes for simd
const desiredSize = bytes.length + 16;
// sbrk doesn't allocate whole pages so we can ask it for as many bytes as we want.
let memoryOffset = Module._sbrk(desiredSize);
if (<any>memoryOffset <= 0) {
// sbrk failed. Due to identical bugs in v8 and spidermonkey, this isn't guaranteed to be OOM.
// We use this function early during startup, when OOM shouldn't be possible anyway!
// Log a warning, then retry.View on GitHub (pinned to 60108ba66e)