fix(daemon,serve): handle log WriteStream and HTTP body stream errors - #280
fix(daemon,serve): handle log WriteStream and HTTP body stream errors#280SebTardif wants to merge 1 commit into
Conversation
Attach an error listener when opening the daemon log file so ENOSPC/EIO cannot become an uncaughtException. Pipe serve response bodies through pipeline() so client abort and body failure destroy both sides. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
Codex review: needs real behavior proof before merge. Reviewed August 6, 2026, 11:54 PM ET / August 7, 2026, 03:54 UTC. ClawSweeper reviewWhat this changesThe PR adds immediate daemon log-stream error handling and replaces one-way HTTP body piping with a bidirectional Node stream pipeline so either endpoint is cleaned up after I/O errors. Merge readiness⛔ Blocked until stronger real behavior proof is added - 3 items remain Keep open: current main still has both stream-error gaps, and no patch defect was found. The HTTP half still needs real serving-boundary proof before merge. Likely related people: steipete (medium confidence). Priority: P1 Review scores
Verification
How this fits togetherDaemon logging mirrors daemon activity to an optional local file, while the HTTP serve path forwards MCP handler response bodies to connecting clients. Both are long-lived I/O boundaries where stream failures must not crash the daemon or leave an upstream body alive. flowchart LR
A[Daemon events] --> B[Log writer]
B --> C[Local log file]
D[MCP handler response] --> E[Response body stream]
E --> F[HTTP response]
F --> G[Client connection]
B --> H[Error containment]
E --> H
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Keep the focused listener and pipeline approach, supported by a redacted real serveHttp/client-abort trace that demonstrates body destruction after the client disconnects. Do we have a high-confidence way to reproduce the issue? No for the complete reported behavior: current source establishes the missing listener and one-way pipe, but the supplied HTTP evidence does not exercise a real serve endpoint and aborting client. Is this the best way to solve the issue? Yes in design: Node pipeline is the appropriate narrow primitive for bidirectional stream teardown, pending proof at the actual HTTP serving boundary. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 5f30f68d044b. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (6 earlier review cycles)
|
What Problem This Solves
Two long-lived Node stream paths in mcporter can take down or leak work under ordinary I/O failures:
createLogContext): the appendWriteStreamhad noerrorlistener untildispose. Disk-full / EIO on that stream becomes an uncaughtException and kills the daemon process.handleNodeRequest): onlybody.on('error')destroyed the response. Client abort / response-side errors did not destroy the body stream, so partial writes and open readers could leak until GC.Summary
errorlistener immediately after opening the daemon logWriteStream; warn, drop the writer, and keep logging to console.pipeline()(exported aspipeHttpResponseBody) so body and HTTP response clean each other up on either side error.Evidence
Live
nodeagainst a build of this branch (not a test runner):Without the log fix,
listenerCount('error')is 0 and emitting ENOSPC throws as an uncaught exception. Without the serve fix, client-side response errors leave the body stream alive.Real behavior proof
Behavior or issue addressed: Daemon log WriteStream errors no longer crash the process; HTTP serve body/response errors clean up both sides of the pipe.
Real environment tested: macOS, Node v26.5.1, mcporter built from this branch under /tmp/oc-mcporter-pr.
Exact steps or command run after this patch: Built with
pnpm build, then ran a shortnodescript that opens a daemon log context, emits ENOSPC on the writer, and pipes a Readable throughpipeHttpResponseBodywhile the destination emitssocket hang up.Evidence after fix: terminal output from the patched build:
Observed result after fix: ENOSPC is logged and the writer is cleared with zero uncaught exceptions; response-side errors destroy the request body stream.
What was not tested: Full multi-hour daemon under real disk pressure, and live MCP clients aborting mid-tool-response on a production host.
Test plan
tests/daemon-log-context.test.tsfailed on main behavior (0 error listeners / uncaught ENOSPC), passes with the fixtests/serve-stream-errors.test.tsfailed with one-way pipe (hang / uncaught), passes withpipelinepnpm check(format, oxlint, typecheck)pnpm exec vitest run tests/daemon-log-context.test.ts tests/serve-stream-errors.test.ts tests/serve.test.ts tests/serve-edge.test.ts