herdrdev/herdr · error

ssh bridge stdout missing

Error message

ssh bridge stdout missing

What it means

The SSH bridge child was spawned with Stdio::piped() for stdout, but child.stdout was None when taken. This BrokenPipe error means herdr cannot read output from the ssh process, so the bridge cannot relay data back from the remote.

Source

Thrown at src/remote/attach.rs:1845

    command
        .arg("-T")
        .arg(target)
        .arg(remote_bridge_command(remote_herdr, session_name))
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::inherit());

    let mut child = command
        .spawn()
        .map_err(|err| io::Error::new(err.kind(), format!("failed to start ssh bridge: {err}")))?;
    let mut child_stdin = child
        .stdin
        .take()
        .ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe, "ssh bridge stdin missing"))?;
    let mut child_stdout = child
        .stdout
        .take()
        .ok_or_else(|| io::Error::new(io::ErrorKind::BrokenPipe, "ssh bridge stdout missing"))?;
    let mut stream_to_child = stream.try_clone()?;
    let mut child_to_stream = stream;

    let upload = thread::spawn(move || {
        let _ = copy_flush(&mut stream_to_child, &mut child_stdin);
    });
    let download = thread::spawn(move || {
        let _ = copy_flush(&mut child_stdout, &mut child_to_stream);
        let _ = crate::ipc::shutdown_local_stream_write(&child_to_stream);
    });

    let status = child.wait()?;
    let _ = upload.join();
    let _ = download.join();

    if status.success() {
        Ok(())
    } else {

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Retry the attach operation
  2. Raise file descriptor limits (ulimit -n 4096) if running under a constrained shell
  3. Report reproducible occurrences upstream with logs
Defensive patterns

Strategy: retry

Try / catch

if let Err(e) = bridge() {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        return bridge(); // retry transient handle loss
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Taking .stdout on the freshly spawned bridge Child returns None — an internal invariant failure in bridge setup, or fd exhaustion interfering with pipe handles.

Common situations: Extremely rare; usually fd limit pressure or a regression in bridge construction. Distinct from network failures, which occur later during copy loops.

Related errors


AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28). Data as JSON: /api/errors/2e81b892aea6cbf5. Report an issue: GitHub.