[Bug] Off-heap memory leak: RSS grows 400–500 MB/min while idle, reaches multi-GB

Open 💬 5 comments Opened Jun 11, 2026 by georges-titanx

Memory leak: claude process grows ~400–500 MB/min while idle (off-heap), reaches multi-GB in minutes

Summary

The Claude Code CLI process leaks memory continuously, including while completely idle (no user input, no tool calls). RSS climbs roughly 400–500 MB per minute and reaches 6–7.5 GB within ~10 minutes of a session. The growth is in anonymous/native memory, not the V8 JS heap, and is unrelated to on-disk data, transcripts, file watchers, or child processes. Persisted across multiple daily auto-updates over the last 3 days.

Environment

  • Claude Code version: 2.1.170 (native installer)
  • OS: Ubuntu 24.04.4 LTS, Linux 6.17.0-35-generic, x86_64
  • Total RAM: 31 GiB
  • Install type: native (~/.local/share/claude/versions/, symlinked from ~/.local/bin/claude)
  • Model: opus[1m] (1M context window)
  • Relevant settings.json:

``json
{
"env": { "NODE_OPTIONS": "--max-old-space-size=4096" },
"permissions": { "defaultMode": "auto" },
"model": "opus[1m]",
"verbose": true,
"skipAutoPermissionPrompt": true
}
``

Impact

  • Sessions consume multiple GB of RAM within minutes; on smaller machines this would OOM.
  • Because RSS (7.5 GB) far exceeds the --max-old-space-size=4096 JS-heap cap, the process does not hit a clean V8 OOM — it keeps growing in native memory until the OS is exhausted.
  • Persisted across updates 2.1.168 → 2.1.169 → 2.1.170.

Evidence / diagnostics

1. Growth while idle (no activity between samples)

t+0s    6143 MB
t+15s   6244 MB
t+30s   6343 MB        # ≈ +400 MB/min, steady, zero user interaction
...
@10:36 elapsed: 7495 MB
@06:13 elapsed: ~6168 MB

2. Memory is anonymous/native, not file-mapped (smaps_rollup)

Rss:             6,186,780 kB
Anonymous:       6,071,984 kB   <- ~99% of RSS, private-dirty
Pss_File:          112,250 kB   <- mapped binary, normal
Shared_Clean:        2,588 kB

3. Leak is OFF the JS heap

  • --max-old-space-size=4096 caps the V8 old-space at 4 GB, yet RSS reaches 7.5 GB without an OOM.
  • Strongly implies the leak is in external/native allocations (Node Buffer/ArrayBuffer/WASM/streaming buffers), not retained JS objects.

4. External causes ruled out

  • File watchers: only 2 inotify watches held by the process (despite heavy next dev / tsx watch / nodemon file churn in the working tree — not being watched).
  • Child processes: none spawned by the leaking process.
  • File descriptors: 27 total (6× /dev/pts, 2× /dev/urandom, etc.) — no FD leak.
  • Threads: 20 — stable.
  • On-disk data: ~/.claude.json = 40 K; largest session transcript = 27 MB; ~/.claude/sessions = 8 K. Nothing on disk is large enough to explain the RAM.

Steps to reproduce (observed)

  1. Start a session with model: opus[1m], verbose: true, NODE_OPTIONS=--max-old-space-size=4096.
  2. Leave it idle (or do light work).
  3. Sample grep VmRSS /proc/<pid>/status every 15 s.
  4. Observe steady ~400–500 MB/min RSS growth with no activity.

Hypotheses for the team

Given the leak is off-heap, grows while idle, and the session uses the 1M-context model with verbose logging, likely suspects:

  • A background loop (TUI render tick, telemetry flush, or remote MCP keepalive/poll) retaining Buffer/stream chunks. (This environment has many claude.ai remote MCP servers configured — Atlassian, Cloudflare, Gmail, Slack, Supabase, Vercel, monday.com, TitanX, etc.)
  • 1M-context buffers and/or verbose log buffers not being released between turns.

Secondary bug: failed auto-update artifact

A zero-byte version file is left behind by a failed update, which appears to block moving off the leaky build:

245434064  2.1.168
247297744  2.1.169
247469776  2.1.170   <- active symlink
        0  2.1.173   <- 0-byte, failed/partial download

.last-update-result.json reports the last successful update as 2.1.169 → 2.1.170; the 2.1.173 attempt left a 0-byte file with no recorded outcome.

What I tried

  • Daily auto-updates for 3 days — leak unchanged.
  • Confirmed not config/data/transcript size, not file watchers, not child processes or FD leaks.
  • Restarting the session reclaims all the memory immediately, but it climbs again at the same rate.

View original on GitHub ↗

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