Desktop app: artifact-preview renderers leak ~1GB/hour, are never reaped, and survive app restarts
Status Fixed / completed
Reported on v2.1.209
Maintainer reply None cached
Workaround ✓ Mentioned in description ↑
Activity 0 comments · opened Jul 20, 2026 · closed Jul 21, 2026
Bug report: Claude Desktop artifact-preview renderers leak ~1GB/hour and are never reaped
Environment: Claude Desktop on macOS (Darwin 25.5.0), 16GB M-series Mac. Claude Code sessions hosted in-app (CLI 2.1.209 / 2.1.215).
Summary
Artifact/HTML-preview renderer processes (*.frame.claudeusercontent.com) grow without bound at roughly 0.5–1.2 GB/hour, independent of artifact content. Preview servers stay running forever and are restored across app restarts, so a background preview frame can live for days. On a 16GB machine this filled 22GB of swap (96%) and drove system-wide memory pressure to warning for 7+ hours.
Evidence
- 12–13GB single renderer. A preview renderer (hosting one HTML artifact prototype) reached a 13GB phys_footprint after ~23h alive.
footprintshows the growth entirely in Chromium allocator-tagged anonymous memory: 24,570 dirty regions of ~512KB (V8/PartitionAlloc pattern), system malloc under 1MB. Classic retained-JS/detached-DOM leak, not native. - Content-independent, reproduces 3-for-3. Two fresh preview renderers created the same morning (one interactive dashboard prototype, one static text report) both reached ~2.5GB in ~2 hours (~1.2GB/h each). Same rate on unrelated content implicates the shared preview harness or the event/postMessage stream it subscribes to, not the artifact HTML.
- Leaked pages compress 5.6:1 in the macOS compressor (2.44M compressed pages in 436K physical) — monotonically accumulated repetitive string/JSON state.
- No reaper. html-preview servers remain status
runningindefinitely and are restored at app launch (observed a preview server restored seconds after restart, giving its frame a 22.5h background lifetime). - Telemetry is RSS-only, so the app never notices.
[process-memory]lines reported the 12GB renderer at ~64MB throughout (its RSS after swap-out). No OOM/unresponsive event ever fired. - Separate but related: finished headless Claude Code session processes (scheduled tasks and closed chats,
claude --output-format stream-jsonchildren) are never terminated — 7 accumulated over a day at 100–350MB each. CliGovernor loggedmemory pressure (warning): would evict 0 idle session(s)1,193 times without ever evicting anything.
Suggested fixes
- Reap or suspend preview renderers when their artifact is not visible; cap preview-server lifetime.
- Fix the retention leak in the preview frame wrapper (likely unpruned message/state buffers).
- Sample phys_footprint (not RSS) in process-memory telemetry so eviction logic can actually see pressure.
- Terminate headless CLI session processes once their session completes or idles beyond a threshold.
Impact
16GB machine rendered near-unusable (swap 96%, hourly memory-pressure warnings) after ~1 day of normal use with artifacts + scheduled tasks. Workaround: daily app restart + external watchdog.