fix(supervisor): suppress unhandled stream errors on child stdout/stderr#99802
Conversation
Child process stdout and stderr streams can emit 'error' events (EPIPE, resource limits, I/O errors) that crash the process when no listener is attached. Add noop error handlers to prevent crashes while preserving normal data/end/close event flow. Co-Authored-By: Claude <[email protected]>
|
Codex review: needs maintainer review before merge. Reviewed July 4, 2026, 1:47 AM ET / 05:47 UTC. Summary PR surface: Source +5, Tests +38. Total +43 across 2 files. Reproducibility: yes. at source level: current main has no child stdout/stderr error listener during adapter construction, while the supervisor registers output subscribers only after createChildAdapter returns. A Node probe also confirms unhandled error events throw unless an error listener is installed. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Next step before merge
Security Review detailsBest possible solution: Land the narrow child-adapter lifecycle guard after normal CI and maintainer merge gates, keeping decoder flush and Windows drain settlement owned by the existing close handlers. Do we have a high-confidence way to reproduce the issue? Yes at source level: current main has no child stdout/stderr error listener during adapter construction, while the supervisor registers output subscribers only after createChildAdapter returns. A Node probe also confirms unhandled error events throw unless an error listener is installed. Is this the best way to solve the issue? Yes: the child adapter is the right owner boundary because it owns the child streams from spawn through wait/dispose, and installing one guard at construction closes the timing gap. Subscriber-level guards were too late, and the PTY sibling is unaffected because it does not expose separate stdout/stderr streams. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 1b84316a91dc. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +5, Tests +38. Total +43 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
Co-Authored-By: Claude <[email protected]>
|
maintainer repair and exact-head proof are complete on changes:
validation:
the PR body now contains the durable lifecycle evidence. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Merged via squash.
|
…err (openclaw#99802) * fix(supervisor): suppress unhandled stream errors on child stdout/stderr Child process stdout and stderr streams can emit 'error' events (EPIPE, resource limits, I/O errors) that crash the process when no listener is attached. Add noop error handlers to prevent crashes while preserving normal data/end/close event flow. Co-Authored-By: Claude <[email protected]> * test(supervisor): add regression test for stream error suppression Co-Authored-By: Claude <[email protected]> * fix(supervisor): guard child stream errors during setup --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
What Problem This Solves
Fixes an issue where a supervised child process could crash OpenClaw if stdout or stderr emitted an error after spawn but before the supervisor registered output subscribers.
Why This Change Was Made
The child adapter now installs exactly one stream-lifetime error guard on stdout and stderr during adapter construction. Subscriber registration remains responsible only for decoding data; existing stream
closehandlers continue to own decoder flush and Windows drain completion.User Impact
Early child output-stream failures no longer escape as unhandled Node
errorevents. Repeated output subscriptions do not accumulate redundant permanent error listeners, and process wait behavior remains unchanged.Evidence
node scripts/run-vitest.mjs src/process/supervisor/adapters/child.test.ts(19 passed).wait()settles only after stream close.errorthenclose.oxfmtandgit diff --checkpassed.a968528d469c3b4e1ca1b7701b84854d9f92160b.