[BUG] Memory leak: auto-update download Response (2.5 GB) not released after fetch completes

Resolved 💬 3 comments Opened Mar 10, 2026 by XinyuLiuCs Closed Mar 13, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code leaks ~2.5 GB of memory within 5 minutes of startup. Heap dump analysis pinpoints the root cause to the auto-update mechanism: the HTTP Response object from downloading the update binary is never released after the download completes.

A single Response object fetching the v2.1.72 update binary holds 223 MB directly, and the associated 8,801 ArrayBuffer chunks total 2.21 GB. These are retained by a pending Promise in an async generator, preventing GC from reclaiming any of it.

Heap Dump Analysis

Memory overview (at ~335 seconds uptime):

| Metric | Value |
|--------|-------|
| RSS | 2.54 GB |
| Heap Used | 2.77 GB |
| External Memory | 2.74 GB |
| ArrayBuffers | 2.23 GB |
| Growth Rate | ~27 GB/hour |

Top objects by self size:

| # | Type | Name | Size |
|---|------|------|------|
| 1 | native | Response | 223.16 MB |
| 2 | object | ArrayBuffer (×8801) | 2,211 MB total |
| 3 | native | Blob (×15) | 9.94 MB total |

The leaking Response URL:

https://storage.googleapis.com/claude-code-dist-.../claude-code-releases/2.1.72/linux-x64/claude

Retention chain:

(root)
  └─ GlobalObject
      └─ InternalModuleRegistry
          └─ Object (http module exports)
              └─ JSLexicalEnvironment (bundled code, 195 KB)
                  └─ Generator → pending Promise (never resolves)
                      └─ IncomingMessage
                          └─ FetchAPI → Response (223 MB)
                              └─ ReadableStream body → ArrayBuffers (2.2 GB)

The key issue: an async generator holds a reference to the Response via a JSLexicalEnvironment closure. The generator is suspended on a pending Promise that never resolves, so the entire response body (streamed into thousands of ArrayBuffer chunks) is permanently retained.

What Should Happen?

After the auto-update binary is downloaded and written to disk, the Response object and all associated ArrayBuffer chunks should be released (e.g., by calling response.body.cancel(), nullifying references, or ensuring the consuming async generator completes/returns).

Steps to Reproduce

  1. Open Claude Code v2.1.71 on Linux (WSL2 Ubuntu) when a newer version (2.1.72) is available
  2. Wait ~5 minutes
  3. Observe memory usage climbing to 2.5+ GB
  4. Take a heap dump (/heapdump) and observe the ResponseArrayBuffer retention chain

Error Messages/Logs

Diagnostics JSON from /heapdump:

{
  "memoryUsage": {
    "heapUsed": 2774169282,
    "heapTotal": 46575616,
    "external": 2735764610,
    "arrayBuffers": 2338137054,
    "rss": 2663563264
  },
  "memoryGrowthRate": {
    "bytesPerSecond": 7946604.73,
    "mbPerHour": 27282.50
  },
  "analysis": {
    "potentialLeaks": ["High memory growth rate: 27282.5 MB/hour"],
    "recommendation": "WARNING: 1 potential leak indicator(s) found."
  }
}

Claude Model

Opus

Is this a regression?

I don't know

Claude Code Version

2.1.71

Platform

Anthropic API

Operating System

Linux (WSL2 Ubuntu on Windows, kernel 6.6.87.2-microsoft-standard-WSL2)

Terminal/Shell

Bash

Additional Information

  • Node.js version: v24.3.0
  • The heap snapshot file is 34 MB and available upon request
  • This likely explains many of the open memory leak reports (#31621, #25023, #24827, #17615, etc.) — they may all share this same root cause
  • Suggested fix: ensure the update download response stream is properly consumed and closed, and that no async generator keeps a dangling reference to the Response object

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗