Skip to content

Capture the subprocess stderr you were told to check

Problem

A client library spawns a subprocess. The subprocess dies. The library reports:

process exited with code 1 — check stderr output for details

There is no stderr to check. The library never captured it, and the stream went to a file descriptor nobody was reading. The error message names the one artifact that would explain the failure and that the library just discarded.

Technique

Pass a stderr callback at construction, always, as a default rather than a debugging step:

options = ClientOptions(
    ...,
    stderr=lambda line: logger.warning("subprocess: %s", line),
)

Log at warning level under a labelled logger, so lines from concurrent subprocesses stay attributable and appear in normal operation rather than only when someone thinks to raise the log level.

The cost is a callback. The benefit is that the next crash explains itself instead of requiring a reproduction.

When it applies

Every subprocess-spawning client where the library treats stderr capture as opt-in. It is worth doing before you have a problem: the failures that need it are precisely the intermittent ones you cannot reproduce on demand.

When it does NOT apply

Where the subprocess writes its diagnostics somewhere you already collect — a log file, a logging socket — a second copy adds noise.

Be careful with very chatty subprocesses. If it writes a progress bar to stderr, logging every line at warning will bury real signal, and the fix is to filter in the callback rather than to drop it.

Evidence

An agent runtime reported check stderr output for details on exit-code-1 crashes for weeks. Adding the callback surfaced the real cause on the first recurrence — a protocol stream corrupted by a library writing to stdout.

Two lessons, and the second is the transferable one. The diagnostic existed the whole time and was thrown away by default. And the error message pointed directly at it, which made the omission look like the reader's mistake rather than the library's.

See also