xai-org/grok-build · error

failed to spawn {bin}: {e}

Error message

failed to spawn {bin}: {e}

What it means

The CLI clipboard write helper at crates/codegen/xai-grok-shared/src/clipboard.rs:1810 spawns an external write tool (bin, e.g. wl-copy or xclip) and maps a spawn failure to this error. A later non-zero exit is reported separately as '{bin} exited with status'. This is purely a launch failure.

Source

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

    fn run_pipe_in(argv: &[&str], data: &[u8]) -> anyhow::Result<()> {
        let (bin, args) = argv.split_first().expect("argv non-empty");

        // Spooled stdin (`spool_for_stdin`), not a pipe: clipboard tools
        // (wl-copy/xclip) daemonize and read the payload after forking, racing
        // a pipe write and possibly leaving the selection empty; the daemon
        // keeps its fd to the unlinked temp file.
        let stdin = super::spool_for_stdin(data)?;

        let mut cmd = Command::new(bin);
        cmd.args(args)
            .stdin(Stdio::from(stdin))
            .stdout(Stdio::null())
            .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 spawn {bin}: {e}"))?;
        let status = super::wait_with_deadline(&mut child, CLI_WRITE_WAIT)?;
        if !status.success() {
            anyhow::bail!("{bin} exited with status {status}");
        }
        Ok(())
    }

    /// 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())

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Install the appropriate tool: `wl-clipboard` (Wayland) or `xclip`/`xsel` (X11); confirm with `which <bin>`.
  2. Pick the backend matching the session: WAYLAND_DISPLAY vs DISPLAY.
  3. Fix PATH for the invoking process.
  4. Fall back to the arboard backend when no CLI tool exists.

Example fix

// before
run_write_bin("wl-copy", input)?;
// after
let bin = if std::env::var_os("WAYLAND_DISPLAY").is_some() { "wl-copy" } else { "xclip" };
if which(bin).is_some() { run_write_bin(bin, input)?; } else { arboard_set_text(&input)?; }
Defensive patterns

Strategy: validation

Validate before calling

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

Prevention

When it happens

Trigger: Writing the clipboard on Linux with the chosen binary (wl-copy/xclip/xsel) not installed, not on PATH, or not executable; the wait is bounded by wait_with_deadline(CLI_WRITE_WAIT).

Common situations: Wayland users lacking wl-copy, X11 users lacking xclip; minimal Docker images; mismatch between session type and installed tool (running wl-copy under X11-only envs).

Related errors


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