sigoden/aichat · error
Tool call exit with
Error message
Tool call exit with {exit_code} What it means
`run_llm_function` executes the function's command via `run_command` and treats a non-zero exit code as a tool failure, bubbling up 'Tool call exit with {exit_code}'. The tool subprocess ran but reported failure.
Solutions
- Run the configured command manually with the same args/env to see the underlying failure
- Fix the command or its arguments in the function config
- Make the tool script exit 0 while writing a structured error to the output temp file
- Check required env vars/dependencies for the tool
Example fix
// before
my_tool = { command = "mytool --strict" }
// after: tolerate expected failures in the script
my_tool = { command = "mytool || echo '{\"error\": \"handled\"}'" } Defensive patterns
Strategy: try-catch
Validate before calling
let status = std::process::Command::new(cmd)
.args(&args)
.status()?;
if !status.success() {
eprintln!("tool command would fail with {}", status.code().unwrap_or(-1));
} Try / catch
match run_llm_function(cmd_name, cmd_args, envs).await {
Err(e) if e.to_string().starts_with("Tool call exit with") => {
eprintln!("Tool subprocess failed; inspect command and env");
}
other => other?,
} Prevention
- Test each configured tool command manually before wiring it up
- Make tool scripts exit 0 and encode failures in their JSON output
- Verify env vars and dependencies the tool needs are present
When it happens
Trigger: The command configured for the LLM function (run by `run_instructions_fn` or `eval`) exits with a non-zero status.
Common situations: Shell command in the function config fails (missing binary, bad flags, script error); environment vars passed via `envs` are wrong; the tool needs network/credentials that aren't present.
Related errors
- The request was aborted because an infinite loop of…
- The call ' ' has invalid arguments
- Unexpected call
- No command generated
- Invalid messages
AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09).
Data as JSON: /api/errors/cf465c804a459436.
Report an issue: GitHub.
Appendix: source
Thrown at src/function.rs:282
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") {
for name in exts.split(';').map(|ext| format!("{cmd_name}{ext}")) {
for dir in bin_dir {View on GitHub (pinned to 82976d349a)