Description
Claude Code leaks ~490 MB/hour of external (native) ArrayBuffer memory. A 34-minute session accumulated 3.39 GB of external memory (2.92 GB in ArrayBuffers), while the V8 heap itself remained healthy at ~126 MB.
The memory is invisible to V8 heap snapshots — it lives in native/external allocations tracked by V8 but not captured in .heapsnapshot files. This points to a leak in the HTTP streaming layer (likely undici response body buffers not being freed).
Environment
- Claude Code version: 2.1.72
- Node.js version: v24.3.0
- Platform: macOS Darwin 25.3.0 (Apple Silicon)
- Model: claude-opus-4-6
Reproduction
- Start a Claude Code session
- Use it normally (chat, tool calls, web fetches, file reads)
- After ~30 minutes, run
/heapdump
- Observe external memory growing at ~490 MB/hour
Diagnostics Data
From the diagnostics JSON (/heapdump output):
{
"uptimeSeconds": 2033.87,
"memoryUsage": {
"heapUsed": 3511037332,
"heapTotal": 136690688,
"external": 3392535811,
"arrayBuffers": 2915585335,
"rss": 290684928
},
"memoryGrowthRate": {
"bytesPerSecond": 142922.24,
"mbPerHour": 490.68
},
"v8HeapStats": {
"heapSizeLimit": 12440698880,
"mallocedMemory": 3511299731,
"peakMallocedMemory": 1244069888,
"detachedContexts": 0,
"nativeContexts": 1
},
"resourceUsage": {
"maxRSS": 1273927565312
}
}
Heap Snapshot Analysis
The V8 heap snapshot (76 MB serialized) shows the JS heap is healthy at ~126 MB. The top consumers are:
| Category |
Size |
Notes |
[object] Object |
20.1 MB |
419K objects — normal |
[object] ArrayBuffer |
19.0 MB |
8 ArrayBuffers (V8-managed, tiny vs the 2.92 GB external) |
[code] FunctionCodeBlock |
14.0 MB |
4,261 blocks — normal |
[native] Blob |
9.8 MB |
7 Blobs retained by a single Array(6) |
[closure] Function |
4.3 MB |
136K closures — normal |
The 16 MB ArrayBuffer is retained by WebAssembly.Memory (expected — likely argon2/crypto).
Additional observations
- Duplicated skill definitions: Every skill appears twice in memory (~800 KB wasted)
- Duplicated conversation context: 6 copies of the same drizzle/postgres schema (~650 KB)
- Base64 PNG screenshots: 2x 582 KB each (1.1 MB)
maxRSS reports 1.18 TB — clearly a Node v24.3.0 reporting bug on macOS (ru_maxrss units issue)
Root Cause Hypothesis
The 2.92 GB of external ArrayBuffers are not captured in the heap snapshot (V8 limitation for external/native memory). The most likely source is undici HTTP response body buffers from Anthropic API streaming responses not being garbage collected. The growth is linear (~490 MB/hour), suggesting each API response's buffer is retained indefinitely.
Workaround
Restart Claude Code sessions every 1-2 hours to reclaim memory.
Description
Claude Code leaks ~490 MB/hour of external (native) ArrayBuffer memory. A 34-minute session accumulated 3.39 GB of external memory (2.92 GB in ArrayBuffers), while the V8 heap itself remained healthy at ~126 MB.
The memory is invisible to V8 heap snapshots — it lives in native/external allocations tracked by V8 but not captured in
.heapsnapshotfiles. This points to a leak in the HTTP streaming layer (likely undici response body buffers not being freed).Environment
Reproduction
/heapdumpDiagnostics Data
From the diagnostics JSON (
/heapdumpoutput):{ "uptimeSeconds": 2033.87, "memoryUsage": { "heapUsed": 3511037332, "heapTotal": 136690688, "external": 3392535811, "arrayBuffers": 2915585335, "rss": 290684928 }, "memoryGrowthRate": { "bytesPerSecond": 142922.24, "mbPerHour": 490.68 }, "v8HeapStats": { "heapSizeLimit": 12440698880, "mallocedMemory": 3511299731, "peakMallocedMemory": 1244069888, "detachedContexts": 0, "nativeContexts": 1 }, "resourceUsage": { "maxRSS": 1273927565312 } }Heap Snapshot Analysis
The V8 heap snapshot (76 MB serialized) shows the JS heap is healthy at ~126 MB. The top consumers are:
[object] Object[object] ArrayBuffer[code] FunctionCodeBlock[native] Blob[closure] FunctionThe 16 MB ArrayBuffer is retained by
WebAssembly.Memory(expected — likely argon2/crypto).Additional observations
maxRSSreports 1.18 TB — clearly a Node v24.3.0 reporting bug on macOS (ru_maxrssunits issue)Root Cause Hypothesis
The 2.92 GB of external ArrayBuffers are not captured in the heap snapshot (V8 limitation for external/native memory). The most likely source is undici HTTP response body buffers from Anthropic API streaming responses not being garbage collected. The growth is linear (~490 MB/hour), suggesting each API response's buffer is retained indefinitely.
Workaround
Restart Claude Code sessions every 1-2 hours to reclaim memory.