jdx/mise · error

failed to read command {stream}: {err}

Error message

failed to read command {stream}: {err}

What it means

While consuming hashed output streams, a read on the child's stdout or stderr pipe failed; cmd.rs surfaces it as `failed to read command <stream>: <err>` (stream identifies stdout/stderr, err is the underlying IO error). This usually means the pipe was broken or the OS returned an error mid-read.

Source

Thrown at src/cmd.rs:1395

        let mut output_bytes = 0usize;
        let mut consume = |output: HashedProcessOutput| -> Result<()> {
            match output {
                HashedProcessOutput::Stdout(bytes) => {
                    output_bytes = output_bytes.saturating_add(bytes.len());
                    if output_bytes > max_output_bytes {
                        bail!("command output exceeded {max_output_bytes} bytes");
                    }
                    stdout_hasher.update(&bytes);
                }
                HashedProcessOutput::Stderr(bytes) => {
                    output_bytes = output_bytes.saturating_add(bytes.len());
                    if output_bytes > max_output_bytes {
                        bail!("command output exceeded {max_output_bytes} bytes");
                    }
                    stderr_hasher.update(&bytes);
                }
                HashedProcessOutput::ReadError(stream, err) => {
                    bail!("failed to read command {stream}: {err}");
                }
            }
            Ok(())
        };
        let mut status = None;
        let mut wait = Box::pin(cp.wait());
        loop {
            tokio::select! {
                result = &mut wait, if status.is_none() => {
                    status = Some(result?);
                    break;
                }
                output = rx.recv() => {
                    let Some(output) = output else {
                        status = Some(wait.await?);
                        break;
                    };
                    if let Err(err) = consume(output) {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Check the embedded IO error (`err`) for the root cause (EPIPE/EIO etc.).
  2. Re-run the command; transient pipe errors often disappear on retry.
  3. Investigate whether the child process crashes mid-execution (core dumps, dmesg, OOM killer logs).
  4. Check system resource limits (ulimit -n, pipe/memory pressure) in constrained environments.

Example fix

// before: child crashes mid-output
mise run flaky-task
# failed to read command stdout: Broken pipe (os error 32)
// after: fix child or raise limits
ulimit -n 4096 && mise run flaky-task
Defensive patterns

Strategy: retry

Validate before calling

# check resources before running
ulimit -n; df -h /tmp; free -m

Try / catch

for attempt in 1 2 3; do mise run task && break || { [ $attempt -lt 3 ] && sleep 2; }; done

Prevention

When it happens

Trigger: execute_hashes_async reading a child's stdout/stderr when the OS read fails: the child killed its own end of the pipe abnormally, the fd was closed unexpectedly, or an OS-level IO error (EIO) occurred — distinct from clean EOF (Ok(None)), which breaks the loop normally.

Common situations: Child process crashing while output is still buffered; running out of file descriptors or pipe buffer resources; processes that close their stdio handles unexpectedly; sandboxed/limited CI environments killing processes.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/2a6af38b4c2eaa81. Report an issue: GitHub.