xai-org/grok-build · error
failed to spawn pbcopy: {e}
Error message
failed to spawn pbcopy: {e} What it means
set_text_with_outcome (crates/codegen/xai-grok-shared/src/clipboard.rs:1014) writes text via the macOS `pbcopy` tool; this error wraps the std::io::Error when pbcopy cannot be spawned. It does not indicate pbcopy failed later — a non-zero exit is reported as 'pbcopy exited with status'.
Source
Thrown at crates/codegen/xai-grok-shared/src/clipboard.rs:1014
pub fn set_text_with_outcome(text: &str) -> super::NativeWriteOutcome {
let mut outcome = super::NativeWriteOutcome {
cli_tools_tried: vec!["pbcopy"],
..Default::default()
};
let result = (|| -> anyhow::Result<()> {
// Spooled stdin (not a pipe): a stalled pbcopy must not block the
// UI thread on the write, and the deadline wait needs stdin closed.
let stdin = super::spool_for_stdin(text.as_bytes())?;
let mut cmd = Command::new("pbcopy");
cmd.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 pbcopy: {e}"))?;
let deadline = std::time::Duration::from_secs(2);
let status = super::wait_with_deadline(&mut child, deadline)?;
if !status.success() {
anyhow::bail!("pbcopy exited with status {status}");
}
Ok(())
})();
match result {
Ok(()) => {
outcome.cli_ok = true;
outcome.cli_ok_tools.push("pbcopy");
outcome.any_ok = true;
}
Err(e) => tracing::debug!("pbcopy failed: {e}"),
}
outcome
}
View on GitHub (pinned to bc7f02eddd)
Solutions
- Run on macOS or install/reveal pbcopy; verify with `which pbcopy`.
- Fix the process PATH so /usr/bin is present.
- Prefer the arboard backend when the platform tool is unavailable.
Example fix
// before
set_text_with_outcome(text)?;
// after
if which("pbcopy").is_none() {
arboard_set_text(&text)?;
} else {
set_text_with_outcome(text)?;
} Defensive patterns
Strategy: fallback
Validate before calling
let pbcopy_ok = std::process::Command::new("pbcopy").arg("-v").output().is_ok(); Try / catch
match set_text_with_outcome(text) {
Err(e) if e.to_string().contains("failed to spawn pbcopy") => arboard_set_text(text),
other => other,
} Prevention
- Only use the pbcopy path on macOS (`cfg(target_os = "macos")` or runtime check).
- Verify pbcopy with `which pbcopy` before writing.
- Keep an arboard fallback wired in.
When it happens
Trigger: Calling set_text_with_outcome on a system where pbcopy is missing from PATH or not executable (Linux, minimal container, broken PATH).
Common situations: Cross-platform apps invoking the macOS path by mistake; headless CI runners; PATH sanitization in daemons dropping /usr/bin.
Related errors
- failed to run {label}: {error}
- failed to run osascript: {e}
- {label} exited with {}: {}
- pbcopy exited with status {status}
- osascript failed: {stderr}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/947d009771d5fd22.
Report an issue: GitHub.