Hmbown/CodeWhale · error · anyhow::Error

Failed to wait on {program}: {e}

Error message

Failed to wait on {program}: {e}

What it means

child.wait() on the wl-copy process failed in write_text_with_wlcopy_using_argv. The copy path waits synchronously after stdin drops (the drop closes the pipe so wl-copy flushes). wait() errors are rare infrastructure failures - ECHILD if the child was already reaped elsewhere, or an OS-level interrupt - distinct from wl-copy exiting non-zero, which is a separate bail.

Source

Thrown at crates/tui/src/tui/clipboard.rs:593

}

#[cfg(all(target_os = "linux", not(target_env = "ohos"), not(test)))]
fn write_text_with_wlcopy_using_argv(program: &str, text: &str) -> Result<()> {
    let mut child = Command::new(program)
        .stdin(Stdio::piped())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn()
        .map_err(|e| anyhow::anyhow!("Failed to run {program}: {e}"))?;
    if let Some(mut stdin) = child.stdin.take() {
        stdin
            .write_all(text.as_bytes())
            .map_err(|e| anyhow::anyhow!("Failed to write to {program}: {e}"))?;
    }
    // stdin is dropped here, closing the pipe so wl-copy flushes.
    let status = child
        .wait()
        .map_err(|e| anyhow::anyhow!("Failed to wait on {program}: {e}"))?;
    if !status.success() {
        bail!("{program} exited with {status}");
    }
    Ok(())
}

#[cfg(not(test))]
fn write_text_to_terminal_client(text: &str, in_tmux: bool) -> Result<()> {
    if in_tmux {
        return write_text_with_tmux(text);
    }
    write_text_with_osc52(text)
}

#[cfg(not(test))]
fn write_text_with_tmux(text: &str) -> Result<()> {
    write_text_with_tmux_using_argv("tmux", &[], text)
}

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Reproduce manually: `printf x | wl-copy; echo $?` - if this works, the environment is reaping children
  2. Disable or scope the subreaper/supervisor for the TUI process
  3. Prefer the OSC 52/tmux path in that environment if the issue persists
Defensive patterns

Strategy: try-catch

Try / catch

let status = match child.wait() {
    Ok(status) => status,
    Err(e) if e.raw_os_error() == Some(10) /* ECHILD: reaped elsewhere */ => {
        assume_child_exited(); // supervisor reaped it; not a clipboard failure
        return Ok(());
    }
    Err(e) => return Err(anyhow::anyhow!("Failed to wait on wl-copy: {e}")),
};

Prevention

When it happens

Trigger: std::process::Child::wait returns Err: a subreaper/process supervisor reaped the wl-copy child before the TUI could, pidfd or SIGCHLD handling interfered, or a rare kernel errno during waitpid.

Common situations: Running under containers, systemd user sessions, s6, or any subreaper that reaps grandchildren; global signal-handling libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/d2ffc8f6d8f9df67. Report an issue: GitHub.