Hmbown/CodeWhale · error

Failed to run command

Error message

Failed to run command: {e}

What it means

This error wraps a failed `Command::spawn()` when the TUI launches an external child process with piped stdout/stderr. `spawn()` only fails at exec/startup time — the binary could not be found, permissions were denied, or the OS refused to fork. The message embeds the underlying OS error via anyhow.

Solutions

  1. Check the wrapped OS error text: 'No such file or directory' means the binary path/name is wrong
  2. Use an absolute path to the binary instead of relying on PATH
  3. Verify the file exists and is executable (`which <cmd>`, `chmod +x`)
  4. If child_env::apply_to_command overrides env, confirm PATH is preserved

Example fix

// before
let mut child = cmd.spawn().map_err(|e| anyhow::anyhow!("Failed to run command: {e}"))?;
// after
let program = which::which(&program).map_err(|e| anyhow::anyhow!("command `{program}` not found: {e}"))?;
let mut child = cmd.spawn().map_err(|e| anyhow::anyhow!("Failed to run command `{program}`: {e}"))?;
Defensive patterns

Strategy: try-catch

Validate before calling

const path = whichSync(cmd);
if (!fs.existsSync(path) || !(fs.statSync(path).mode & 0o111)) throw new Error(`${cmd} not executable`);

Type guard

fn is_spawnable(cmd: &str) -> bool {
    which::which(cmd).map(|p| p.is_file()).unwrap_or(false)
}

Try / catch

match cmd.spawn() {
    Ok(child) => child,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
        eprintln!("command not found: {}", program); return;
    }
    Err(e) => return Err(anyhow::anyhow!("Failed to run command: {e}")),
}

Prevention

When it happens

Trigger: Any code path that runs an external command through this helper (e.g. an exec tool) when the program path does not exist, is not executable, or the process cannot be forked.

Common situations: Command name not on PATH or misspelled; binary built for wrong platform; missing execute permission; environment stripping PATH so bare names don't resolve; resource limits preventing fork.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/3532e6988b525924. Report an issue: GitHub.

Appendix: source

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

    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 73e0f67d83)