Skip to content

CLI does not handle asynchronous stream errors (EPIPE) on stdout #409

Description

@bgmcmullen

A try/catch around a write contains a synchronous throw. On a real pipe, process.stdout is a net.Socket and EPIPE is delivered asynchronously as an 'error' event, which no try/catch in the process can contain. With no 'error' listener, that surfaces as an uncaught exception, a stack trace, and a non-zero exit from a command that had already done its work.

This is CLI-wide, not specific to any one command: nothing in bin/hypaware.js installs an 'error' handler on stdout/stderr.

What I could and could not reproduce

Measured on macOS, Node 24.7:

  • hyp query overview | head -1 (and -2, -5): no stack, clean exit. The block is 3,954 bytes, well inside a 64 KB pipe buffer, so the write completes before the reader's exit can matter.
  • hyp query sql "select * from ai_gateway_messages limit 3000" | head -1: also clean, because the row-data budget caps the payload before it can exceed the pipe buffer.
  • A synthetic dead pipe written from a harness: did not raise an uncaught error either.

So I have no live reproduction on today's surfaces. The gap is structural rather than currently-firing: any command that writes more than a pipe buffer's worth to a reader that has exited would hit it, and nothing in the CLI is set up to survive that.

Fix

Install an 'error' handler on stdout/stderr in bin/hypaware.js that exits quietly (0) on EPIPE and reports anything else. That is the conventional CLI behaviour and would let the wizard's first-look comment claim containment without qualification.

Why this is filed rather than fixed

It changes every command's behaviour on a stream error, which deserves its own PR and its own tests (a real pipe, not a stub whose write throws). Raised in review of #407; the comment and test there were corrected to claim only what they actually pin.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions