{"record":{"id":"224b40a6b517ea83","repo":"dotnet/runtime","slug":"out-of-memory","errorCode":null,"errorMessage":"Out of memory","messagePattern":"Out of memory","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/mono/browser/runtime/memory.ts","lineNumber":343,"sourceCode":"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 {\n    const sp = Module.stackSave();\n    const ptr = Module.stackAlloc(bytesWanted);\n    try {\n        return f(ptr, ud1, ud2, ud3);\n    } finally {\n        if (loaderHelpers.is_runtime_running()) Module.stackRestore(sp);\n\n    }\n}\n\n// @bytes must be a typed array. space is allocated for it in the native heap\n//  and it is copied to that location. returns the address of the allocation.\nexport function mono_wasm_load_bytes_into_heap (bytes: Uint8Array): VoidPtr {\n    // pad sizes by 16 bytes for simd\n    const memoryOffset = malloc(bytes.length + 16);\n    if (<any>memoryOffset <= 0) {\n        mono_log_error(`malloc failed to allocate ${(bytes.length + 16)} bytes.`);\n        throw new Error(\"Out of memory\");\n    }\n    const heapBytes = new Uint8Array(localHeapViewU8().buffer, <any>memoryOffset, bytes.length);\n    heapBytes.set(bytes);\n    return memoryOffset;\n}\n\n// @bytes must be a typed array. space is allocated for it in memory\n//  and it is copied to that location. returns the address of the data.\n// the result pointer *cannot* be freed because malloc is bypassed for speed.\nexport function mono_wasm_load_bytes_into_heap_persistent (bytes: Uint8Array): VoidPtr {\n    // pad sizes by 16 bytes for simd\n    const desiredSize = bytes.length + 16;\n    // sbrk doesn't allocate whole pages so we can ask it for as many bytes as we want.\n    let memoryOffset = Module._sbrk(desiredSize);\n    if (<any>memoryOffset <= 0) {\n        // sbrk failed. Due to identical bugs in v8 and spidermonkey, this isn't guaranteed to be OOM.\n        // We use this function early during startup, when OOM shouldn't be possible anyway!\n        // Log a warning, then retry.","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/mono/browser/runtime/memory.ts#L325-L361","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst ptr = mono_wasm_load_bytes_into_heap(hugeBytes);\n// after\nconst chunkSize = 1 << 20;\nfor (let i = 0; i < hugeBytes.length; i += chunkSize) {\n  const chunk = hugeBytes.subarray(i, Math.min(i + chunkSize, hugeBytes.length));\n  mono_wasm_load_bytes_into_heap(chunk);\n}","handlingStrategy":"try-catch","validationCode":"function canAllocateHeap(bytes: Uint8Array): boolean {\n  // rough guard: total requested must be below half of currently free linear memory\n  const free = Module.HEAP8.length; // proxy for current limit\n  return bytes.length + 16 < free;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const ptr = mono_wasm_load_bytes_into_heap(bytes);\n} catch (e) {\n  if ((e as Error).message === 'Out of memory') {\n    // reduce payload, grow memory, or report to user\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["memory","out-of-memory","native-heap","marshaler"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}