Skip to content

fix(engines): swallow EPIPE on subprocess stdin#13

Merged
vxcozy merged 1 commit into
mainfrom
fix/subprocess-stdin-epipe
Apr 11, 2026
Merged

fix(engines): swallow EPIPE on subprocess stdin#13
vxcozy merged 1 commit into
mainfrom
fix/subprocess-stdin-epipe

Conversation

@vxcozy
Copy link
Copy Markdown
Collaborator

@vxcozy vxcozy commented Apr 11, 2026

Summary

  • Attaches an error listener to child.stdin in SubprocessEngine so EPIPE doesn't crash the host process when a subprocess exits before the parent finishes writing.
  • Non-EPIPE stdin errors are surfaced as a text_delta so they don't disappear silently. The exit code path remains the source of truth for failure reporting.

Why

Surfaced as a CI failure on PR #12: all 2711 tests passed, but the runner exited 1 because an uncaught EPIPE bubbled out of subprocess.ts:310 after the test had already completed. Same bug affects the gateway and interactive agent loop in production — any CLI subprocess that dies during launch would take the host process with it.

CI run: https://github.com/ch4p-labs/ch4p/actions/runs/24276136757/job/70890302469

Test plan

  • npx vitest run packages/engines/src/subprocess.test.ts — 71/71 pass, no uncaught errors
  • npx vitest run — 2711/2711 pass, exit code 0
  • corepack pnpm -r build — clean
  • corepack pnpm audit — 0 vulnerabilities
  • CI green on this PR

When a CLI subprocess exits before the parent finishes writing the prompt
(e.g. argument validation fails on launch), Node emits an EPIPE error event
on child.stdin. Without a listener, that error bubbles as an uncaught
exception and crashes whatever process owns the engine — Vitest in CI, the
gateway in production, or the agent loop interactively.

The exit code path that already runs after the subprocess closes is the
source of truth for failure reporting, so silently dropping EPIPE on the
stdin stream is safe. Other error codes are surfaced as a text_delta so
they don't disappear silently.

Surfaced as an uncaught error in the subprocess.test.ts run on PR #12 CI:
all 2711 tests passed but the runner exited 1.
@vxcozy vxcozy merged commit 7ff8d97 into main Apr 11, 2026
5 checks passed
@vxcozy vxcozy deleted the fix/subprocess-stdin-epipe branch April 11, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant