fix(terminal): cap per-session output buffers so massive process outp…#503
Conversation
…ut can't kill the server A process emitting more output than V8's max string length (~536M chars) made string concatenation throw "RangeError: Invalid string length" inside a stdout 'data' handler in terminal-manager.ts. That uncaught exception hits the handler in index.ts which exits the process — the shared MCP server died silently ~4s into the flood and every command from every chat failed until restart. Reported as the "Invalid string length" / "MCP freezing in multiple chats" bugs. Reproduced with a finite ~600MB single-line flood. Fix: - Cap the per-session line buffer at 50MB chars, evicting oldest lines first; lastReadIndex is adjusted so pagination stays correct. - Force-split single lines past 1MB so a process printing without newlines can't grow one unevictable line. - Stop growing the start_process wait buffer after the call resolves and keep only a bounded sliding tail. This also bounds the periodic analyzeProcessState scan, which ran regex over the full accumulated output every 100ms. - Track evicted chars/lines so interact_with_process snapshot offsets remain absolute and join() costs stay bounded. Trade-offs: only the most recent ~50MB of a session's output remains readable (redirect to a file for full logs), and single lines longer than 1MB are split into multiple buffer lines. Adds test/integration/terminal-output-buffer-leak.js, which drives the built TerminalManager in-process with a ~600MB flood that continues after executeCommand returns: asserts the buffer stays capped, the event loop never stalls, the output tail stays readable, and snapshot reads survive eviction. Crashes with "Invalid string length" on unfixed code; passes in ~1s with the fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR hardens per-session output buffering in TerminalManager to prevent V8 "Invalid string length" crashes. Transient stdout/stderr buffers are now capped to recent characters, the line buffer evicts oldest lines when total characters exceed a per-session limit, and snapshot reads are updated to remain valid across eviction by tracking absolute character offsets and evicted character counts. ChangesPer-Session Output Buffering with Eviction
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
… constant The test attached its 'exit' listener after executeCommand resolved, so a flood finishing within the 500ms wait either failed the getSession assert or missed the exit event and burned the 90s deadline. Poll readOutputPaginated().isComplete instead (covers active and completed sessions) and fall back to a since-start snapshot when the session has already completed. Also export MAX_BUFFERED_OUTPUT_CHARS from terminal-manager and import it in the test instead of duplicating the value. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When the 50MB cap has evicted lines, the model previously saw a shrunken totalLines and buffer-relative line numbers with no indication the head of the output was gone. Expose evictedLines on PaginatedOutputResult and append a [WARNING: ...] marker to the read_process_output status header — only when eviction actually occurred — matching the truncation markers used by read_file, list_directory and interact_with_process. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A process emitting more output than V8's max string length (~536M chars) made string concatenation throw "RangeError: Invalid string length" inside a stdout 'data' handler in terminal-manager.ts. That uncaught exception hits the handler in index.ts which exits the process — the shared MCP server died silently ~4s into the flood and every command from every chat failed until restart. Reported as the "Invalid string length" / "MCP freezing in multiple chats" bugs. Reproduced with a finite ~600MB single-line flood.
Fix:
Trade-offs: only the most recent ~50MB of a session's output remains readable (redirect to a file for full logs), and single lines longer than 1MB are split into multiple buffer lines.
Adds test/integration/terminal-output-buffer-leak.js, which drives the built TerminalManager in-process with a ~600MB flood that continues after executeCommand returns: asserts the buffer stays capped, the event loop never stalls, the output tail stays readable, and snapshot reads survive eviction. Crashes with "Invalid string length" on unfixed code; passes in ~1s with the fix.
Summary by CodeRabbit
Bug Fixes
New Features
Tests