fix(desktop,web): contain renderer memory growth and recover from renderer OOM crashes - #5148
fix(desktop,web): contain renderer memory growth and recover from renderer OOM crashes#5148t3dotgg wants to merge 1 commit into
Conversation
…derer crashes Long sessions OOM the Electron renderer at V8's heap ceiling (~3.7GB), leaving a dead white window while agents keep running invisibly. Three containments, no user-visible behavior change: - Collapse superseded context-window.updated activities in the live reducer path. Providers stream these continuously and consumers only read the latest value per turn, but the client retained every row — thousands per long thread. Mirrors the rule the server already applies to snapshots (dropStaleContextWindowActivities), including its malformed-row and per-turn revert semantics. - Drop the sidebar thread-detail prewarm from 10 to 3. Each prewarmed row pins a fully hydrated, live-growing thread subscription for as long as it is visible; cold opens still render instantly from the cached snapshot. - Reload the window on render-process-gone (crashed/oom/abnormal-exit), bounded to 3 attempts per rolling minute so a boot-crash cannot reload-loop. The backend is unaffected by renderer death, so a reload fully rehydrates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces new crash recovery behavior (auto-reload on renderer OOM) and changes how thread activity data is deduplicated to prevent memory growth. While well-bounded and tested, these runtime behavior changes to failure handling and state management warrant human review. You can customize Macroscope's approvability policy. Learn more. |
The desktop renderer OOMs at V8's heap ceiling (~3.7 GB) on long sessions and dies to a white screen (#1686, and the claudeissues mirror users keep hitting). The window frame survives, the renderer doesn't, and agents keep running invisibly behind a dead UI.
Investigation on current main found three renderer-side growth/recovery gaps:
context-window.updatedrows accumulate forever. Providers stream these continuously; consumers only ever read the latest value per turn (walking backwards). The server already collapses them in snapshots (dropStaleContextWindowActivities, perf(server): trim stale context-window rows and drop dead replay RPC #4791) but deliberately left live events untouched — so a long-running session still retains thousands of rows per thread client-side. The reducer now applies the same per-turn collapse on the live path, with identical malformed-row semantics (an unresolvable row never replaces a resolvable one, so the meter can always derive a value).render-process-goneonly logged. The window now reloads on crashed/oom/abnormal-exit, bounded to 3 attempts per rolling minute so a boot-crash can't reload-loop. The backend is a separate process and unaffected, so a reload fully rehydrates — the white screen becomes a ~1s blip instead of data loss.No user-visible behavior change outside crash recovery itself.
Companion to #5147 (server-side OOM containment). Long term, the real fix is moving tool.completed payloads out of the hot paths entirely.
Verification:
Built by Claude Fable 5 in Claude Code.
🤖 Generated with Claude Code
Note
Medium Risk
Changes live event reduction and desktop crash recovery paths; bounded reload limits boot-loop risk, but incorrect collapse rules could affect context-window display or thread activity history.
Overview
Targets renderer heap growth and dead UI after V8 OOM on long desktop sessions without changing normal UX except when the renderer actually crashes.
Client thread state: On live
thread.activity-appended, resolvablecontext-window.updatedrows for the same turn now collapse to the newest (matching server snapshotdropStaleContextWindowActivities). Malformed rows do not replace earlier resolvable ones. This cuts thousands of redundant activity rows per thread over long agent runs.Web sidebar:
SIDEBAR_THREAD_PREWARM_LIMITdrops from 10 → 3, reducing how many visible rows keep full live thread-detail subscriptions (messages + activities) in memory.Desktop main window:
render-process-gonefor crashed / oom / abnormal-exit triggers a bounded reload (500ms delay, max 3 attempts per rolling 60s), so users get a brief rehydrate instead of a permanent white screen while the backend keeps running.Tests cover context-window collapse semantics in
threadReducer.Reviewed by Cursor Bugbot for commit 2d46b95. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix renderer memory growth and recover from renderer OOM crashes in desktop and web
DesktopWindowrenderer: oncrashed,oom, orabnormal-exit, waits 500ms then reloads, up to 3 times per 60s window before giving up and logging only.context-window.updatedactivities inthreadReducer: when a valid (finite, non-negativeusedTokens) update is appended, earlier valid updates for the same turn are dropped; malformed updates are preserved and do not displace valid history.Macroscope summarized 2d46b95.