Skip to content

Memory leak: 2.92 GB external ArrayBuffers after 34 min session (v2.1.72) #33320

@RaiAnsar

Description

@RaiAnsar

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

  1. Start a Claude Code session
  2. Use it normally (chat, tool calls, web fetches, file reads)
  3. After ~30 minutes, run /heapdump
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingduplicateThis issue or pull request already existshas reproHas detailed reproduction stepsperf:memoryplatform:macosIssue specifically occurs on macOSstaleIssue is inactive

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions