IOAccelerator GPU leak is version-dependent, not session-lifetime-dependent: 2.1.14x clean, 2.1.217+ leaks (2.77 GB across 37 sessions)

Status Open
Reported on v2.1.217
Maintainer reply None cached
Activity 0 comments · opened Aug 4, 2026

IOAccelerator GPU leak is version-dependent, not session-lifetime-dependent: 2.1.14x clean, 2.1.217+ leaks (2.77 GB across 37 sessions)

Summary

Re-filing per the close message on #35804 (closed NOT_PLANNED 2026-04-16 by the inactivity bot, now locked). The IOAccelerator leak it described is still present in 2.1.220, five months later.

New evidence this report adds: the leak correlates with the Claude Code version, not with session lifetime or CPU activity. #35804 modeled it as monotonic growth over a session's life. That model does not hold — on this machine the two oldest and busiest processes are the two cleanest.

Environment

  • Apple M4 Mac mini, 24 GB unified memory
  • macOS 26.4.1 (25E253)
  • Claude Code 2.1.141, 2.1.145, 2.1.217, 2.1.218, 2.1.220 running concurrently (37 processes)
  • All installed builds 2.1.217–2.1.221 bundle Bun 1.4.0 (verified via strings)

The version boundary

IOAccelerator dirty pages, from vmmap -summary <pid>:

| Version | Procs | Total IOAccel dirty | Mean per proc |
|---|---|---|---|
| 2.1.141 | 2 | 1.27 MB | 0.63 MB |
| 2.1.145 | 2 | 1.41 MB | 0.70 MB |
| 2.1.217 | 4 | 375.3 MB | 93.8 MB |
| 2.1.218 | 3 | 219.4 MB | 73.1 MB |
| 2.1.220 | 26 | 2176.6 MB | 83.7 MB |
| Total | 37 | 2774 MB | |

Every 2.1.14x process is under 1 MB. Every 2.1.217+ process is 16–331 MB. No overlap between the two groups.

Ruling out lifetime and activity

If the leak were driven by session age or render volume, the oldest/busiest processes would be the worst. They are the best:

| PID | Version | CPU time | Elapsed | IOAccel dirty |
|---|---|---|---|---|
| 37566 | 2.1.145 | 707 min | 75 days | 720 KB |
| 7314 | 2.1.141 | 178 min | 81 days | 640 KB |
| 54797 | 2.1.141 | 168 min | 81 days | 656 KB |
| 40861 | 2.1.145 | 150 min | 75 days | 720 KB |
| 27792 | 2.1.220 | 1.3 min | 1 hour | 89.3 MB |
| 37916 | 2.1.220 | 1.5 min | 2.6 hours | 31.6 MB |
| 3672 | 2.1.220 | 7.2 min | 1.2 days | 108.3 MB |
| 83449 | 2.1.220 | 100 min | 3.8 days | 330.7 MB |

PID 37566 has consumed 540× more CPU than PID 27792 and holds 1/124th the GPU memory.

Within 2.1.220 the value jumps to roughly 90 MB early — PID 27792 reached 89.3 MB after one hour and 1.3 minutes of CPU — then varies without a clean correlation to either axis.

Per-process breakdown

vmmap -summary 83449 (2.1.220, 486 MB footprint):

REGION TYPE                 VIRTUAL  RESIDENT    DIRTY  SWAPPED
IOAccelerator                900.5M    365.1M   336.0M   102.5M
__TEXT                       632.5M    185.3M       0K       0K
JS JIT generated code         64.0M     20.8M    20.8M    14.5M
JS VM Gigacage               128.0M     7040K    7040K     544K
MALLOC_SMALL                  40.0M     1920K    1920K    7696K

325 MB of the 355.7 MB total dirty is IOAccelerator — 91%. The actual JS heap is 7 MB. The conversation is not what costs memory.

System impact

With 37 sessions on a 24 GB machine:

PhysMem: 23G used (2883M wired, 10G compressor), 152M unused
vm.swapusage: total = 15360.00M  used = 14168.94M  free = 1191.06M

Reproduction

# per-process
vmmap -summary $(pgrep -f 'local/bin/claude' | head -1) | grep -E 'IOAccelerator|Physical footprint'

# fleet-wide total
for p in $(pgrep -f "local/bin/claude"); do
  vmmap -summary $p 2>/dev/null | awk '$1=="IOAccelerator" && $2!="(reserved)"{print $4}'
done

RSS does not show this. ps reported 459 MB for PID 83449 against a 486 MB footprint with 325 MB of it GPU-dirty; on lighter sessions the RSS gap is far wider. Use footprint -p or vmmap -summary.

Why the version data matters

The bundled Bun is 1.4.0 for every build I still have on disk (2.1.217–2.1.221), so the regression is not a Bun bump inside that window. The 2.1.141 and 2.1.145 binaries have been pruned from ~/.local/share/claude/versions/, so I cannot check what they shipped — the processes hold deleted images. If those builds carried an older Bun, the bisect target is the Bun upgrade; if not, it is a change in Claude Code's own render path between 2.1.145 and 2.1.217.

Either way the earlier builds demonstrate the leak is not inherent to Ink-on-Bun: a 75-day 2.1.145 session with 707 minutes of CPU sits at 720 KB.

References

  • #35804 — original report, closed NOT_PLANNED by the inactivity bot, locked. Close message directs re-filing.
  • oven-sh/bun#28234 — upstream, still OPEN. Isolated a minimal Ink/React repro on Bun.
  • #24113 — retracted, attributed to a Ghostty terminal bug. Distinct: this allocation is inside the claude process.

View original on GitHub ↗