sigoden/aichat · error · anyhow::Error

Unable to run

Error message

Unable to run {cmd_name}, {err}

What it means

run_llm_function shells out to an external command; if spawning fails (binary missing, permission denied, IO error) the underlying error is wrapped with the command name. Non-zero exits produce a separate 'Tool call exit with N' error instead.

Solutions

  1. Install the command or add its directory to PATH / the configured bin_dirs
  2. Verify the tool name spelling in the function definition
  3. Check file permissions (chmod +x) on the executable

Example fix

// before: cmd not installed
// after
$ cargo install the-tool  # or: export PATH="$PATH:/path/to/tool/bin"
Defensive patterns

Strategy: try-catch

Validate before calling

fn tool_available(cmd: &str, bin_dirs: &[PathBuf]) -> bool {
    which::which(cmd).is_ok() || bin_dirs.iter().any(|d| d.join(cmd).exists())
}

Try / catch

match run_llm_function(f).await {
    Err(e) if e.to_string().starts_with("Unable to run") => {
        eprintln!("Tool not available: {e}"); install_hint();
    }
    other => other?,
}

Prevention

When it happens

Trigger: run_llm_function invoked (via run_instructions_fn or eval) and run_command returns Err — the executable isn't found on PATH or in bin_dirs, or can't be executed.

Common situations: Tool command not installed; PATH missing the tool's bin dir on the current platform; Windows polyfill_cmd_name failing to locate a .cmd/.exe shim; insufficient execute permissions.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/d16db9a40d855eb5. Report an issue: GitHub.

Appendix: source

Thrown at src/function.rs:280

    bin_dirs.push(Config::functions_bin_dir());
    let current_path = std::env::var("PATH").context("No PATH environment variable")?;
    let prepend_path = bin_dirs
        .iter()
        .map(|v| format!("{}{PATH_SEP}", v.display()))
        .collect::<Vec<_>>()
        .join("");
    envs.insert("PATH".into(), format!("{prepend_path}{current_path}"));

    let temp_file = temp_file("-eval-", "");
    envs.insert("LLM_OUTPUT".into(), temp_file.display().to_string());

    #[cfg(windows)]
    let cmd_name = polyfill_cmd_name(&cmd_name, &bin_dirs);
    if *IS_STDOUT_TERMINAL {
        println!("{}", dimmed_text(&prompt));
    }
    let exit_code = run_command(&cmd_name, &cmd_args, Some(envs))
        .map_err(|err| anyhow!("Unable to run {cmd_name}, {err}"))?;
    if exit_code != 0 {
        bail!("Tool call exit with {exit_code}");
    }
    let mut output = None;
    if temp_file.exists() {
        let contents =
            fs::read_to_string(temp_file).context("Failed to retrieve tool call output")?;
        if !contents.is_empty() {
            output = Some(contents);
        }
    };
    Ok(output)
}

#[cfg(windows)]
fn polyfill_cmd_name<T: AsRef<Path>>(cmd_name: &str, bin_dir: &[T]) -> String {
    let cmd_name = cmd_name.to_string();
    if let Ok(exts) = std::env::var("PATHEXT") {

View on GitHub (pinned to 82976d349a)