xai-org/grok-build · error

failed to run {bin}: {e}

Error message

failed to run {bin}: {e}

What it means

The CLI clipboard read helper at crates/codegen/xai-grok-shared/src/clipboard.rs:1835 spawns a read tool (e.g. wl-paste/xclip) with piped stdout and maps a spawn failure to this error. stdout is drained on a worker thread so a hung tool can be killed at the deadline; a non-zero exit is reported separately.

Source

Thrown at crates/codegen/xai-grok-shared/src/clipboard.rs:1835

    /// Run a CLI tool and capture its stdout, bounded by `deadline`
    /// (`CLI_PROBE_WAIT` for read-backs, `CLI_READ_WAIT` for content reads).
    #[cfg(target_os = "linux")]
    fn run_capture_out_with_status(
        argv: &[&str],
        deadline: std::time::Duration,
    ) -> anyhow::Result<(std::process::ExitStatus, Vec<u8>)> {
        let (bin, args) = argv.split_first().expect("argv non-empty");
        let mut cmd = Command::new(bin);
        cmd.args(args)
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::null());
        xai_grok_tools::util::detach_std_command(&mut cmd);
        #[allow(clippy::disallowed_methods)] // short-lived clipboard helper, waited on below
        let mut child = cmd
            .spawn()
            .map_err(|e| anyhow::anyhow!("failed to run {bin}: {e}"))?;
        // Drain stdout on a worker so the deadline wait can kill a hung tool
        // without deadlocking on a full pipe; the kill EOFs the pipe and the
        // reader exits on its own.
        let mut stdout = child.stdout.take().expect("stdout piped");
        let reader = std::thread::spawn(move || {
            use std::io::Read;
            let mut buf = Vec::new();
            let _ = stdout.read_to_end(&mut buf);
            buf
        });
        let status = super::wait_with_deadline(&mut child, deadline)?;
        let stdout = reader.join().unwrap_or_default();
        Ok((status, stdout))
    }

    /// Capture CLI stdout. Non-zero exit → empty bytes (typed MIME absent), not Err.
    /// Spawn/timeout failures still return Err. Prefer this over
    /// [`run_capture_out_checked`] for content reads where a missing type is

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Install the matching reader (`wl-clipboard` or `xclip`) and verify with `which <bin>`.
  2. Select the binary based on the active display server.
  3. Correct PATH in the invoking environment.
  4. Use arboard-based reads as a fallback.
Defensive patterns

Strategy: validation

Validate before calling

fn pick_read_bin() -> Option<&'static str> {
    let wayland = std::env::var_os("WAYLAND_DISPLAY").is_some();
    let (preferred, alt) = if wayland { ("wl-paste", "xclip") } else { ("xclip", "wl-paste") };
    [preferred, alt].into_iter().find(|b| which(b).is_some())
}

Prevention

When it happens

Trigger: Reading the clipboard via the CLI path when the binary is missing from PATH, not executable, or the exec fails — same conditions as the write-side spawn error but on the read path.

Common situations: Fresh Linux installs without xclip/wl-paste; containers; running the X11 tool under Wayland or vice versa.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/709089c7d8e0143e. Report an issue: GitHub.