Hmbown/CodeWhale · error

Failed to run command: {e}

Error message

Failed to run command: {e}

What it means

Thrown when std::process::Command::spawn fails while starting the sandboxed child process. The wrapped io::Error is usually NotFound (program not on PATH or bad absolute path), PermissionDenied (file lacks the execute bit, or no interpreter for a script), or a failure resolving exec_env.cwd which is passed to current_dir.

Source

Thrown at crates/tui/src/lib.rs:8931

    let (program, args) = command
        .split_first()
        .ok_or_else(|| anyhow::anyhow!("Command is required"))?;
    let spec =
        CommandSpec::program(program, args.to_vec(), cwd.clone(), timeout).with_policy(policy);
    let manager = SandboxManager::new();
    let exec_env = manager.prepare(&spec);

    let mut cmd = Command::new(exec_env.program());
    cmd.args(exec_env.args())
        .current_dir(&exec_env.cwd)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped());
    child_env::apply_to_command(&mut cmd, child_env::string_map_env(&exec_env.env));

    let mut child = cmd
        .spawn()
        .map_err(|e| anyhow::anyhow!("Failed to run command: {e}"))?;
    let stdout_handle = child
        .stdout
        .take()
        .ok_or_else(|| anyhow::anyhow!("stdout unavailable"))?;
    let stderr_handle = child
        .stderr
        .take()
        .ok_or_else(|| anyhow::anyhow!("stderr unavailable"))?;

    let timeout = exec_env.timeout;
    let stdout_thread = std::thread::spawn(move || {
        let mut reader = stdout_handle;
        let mut buf = Vec::new();
        let _ = reader.read_to_end(&mut buf);
        buf
    });
    let stderr_thread = std::thread::spawn(move || {
        let mut reader = stderr_handle;

View on GitHub (pinned to 8880682c63)

Solutions

  1. Verify the program resolves the same way the sandbox will: run `which <program>` with the child's PATH
  2. chmod +x the target binary or script, and give interpreted scripts a valid shebang
  3. Use an absolute path to the program in the sandbox command configuration
  4. Confirm the cwd passed to the run exists and is a directory (recreate it or pass an absolute cwd)

Example fix

# before: relative script without exec bit
sandbox run -- ./tools/lint.sh
# after
chmod +x /repo/tools/lint.sh
sandbox run -- /repo/tools/lint.sh
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: resolve the program before spawning
fn resolvable(program: &str) -> bool {
    let p = std::path::Path::new(program);
    if p.is_absolute() || p.components().count() > 1 {
        p.is_file()
    } else {
        std::env::var_os("PATH").map_or(false, |paths| {
            std::env::split_paths(&paths).any(|dir| dir.join(program).is_file())
        })
    }
}

Try / catch

match cmd.spawn() {
    Ok(child) => { /* proceed with pipes and wait */ }
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => { /* program missing from PATH: log resolved PATH and cwd */ }
    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => { /* chmod +x or fix shebang */ }
    Err(e) => return Err(anyhow::anyhow!("Failed to run command: {e}")),
}

Prevention

When it happens

Trigger: Sandbox run with a program name absent from the child environment's PATH, an absolute/relative path whose file is not executable, a script without a shebang line, or a cwd (explicit argument or the current-dir fallback) that was deleted.

Common situations: Typos in tool names inside sandbox configs, PATH shims (nvm, virtualenv) missing from the sanitized child environment, files copied without exec bits (git on FAT, container layers with masked permissions), running from a deleted working directory.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/3532e6988b525924. Report an issue: GitHub.