sigoden/aichat · error

The request was aborted because an infinite loop of…

Error message

The request was aborted because an infinite loop of function calls was detected.

What it means

`eval_tool_calls` detects that after deduplicating the model's tool calls, no unique calls remain — the model keeps issuing the same call(s) repeatedly, which the library treats as an infinite function-call loop and aborts. This protects against runaway token spend and endless recursion.

Solutions

  1. Make the tool return meaningful, distinct results so the model stops repeating the call
  2. Improve the system prompt/tool descriptions so the model knows when to stop
  3. Check tool command exit/output handling in `run_llm_function` (a failing tool can cause retries)
  4. Cap loop iterations or dedup window in the agent config

Example fix

// before: tool always returns null
Ok(json!(null))
// after
Ok(json!({"status": "completed", "result": output}))
Defensive patterns

Strategy: try-catch

Validate before calling

if ToolCall::dedup(calls.clone()).is_empty() {
    return Err(anyhow!("tool calls already executed; aborting loop"));
}

Try / catch

match agent.run().await {
    Err(e) if e.to_string().contains("infinite loop of function calls") => {
        eprintln!("Model looped on tool calls; refining prompt/tool output");
    }
    other => other?,
}

Prevention

When it happens

Trigger: `ToolCall::dedup(calls)` returns an empty vector because all requested tool calls were duplicates of previously executed ones; raised from `call_chat_completions`/`call_chat_completions_streaming` agent loops.

Common situations: An LLM keeps re-invoking the same tool with identical arguments because the tool result doesn't satisfy it; a tool returns no useful output so the model retries forever; misconfigured tool schemas cause the model to loop.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/function.rs:28

use std::{
    collections::{HashMap, HashSet},
    fs,
    path::{Path, PathBuf},
};

#[cfg(windows)]
const PATH_SEP: &str = ";";
#[cfg(not(windows))]
const PATH_SEP: &str = ":";

pub fn eval_tool_calls(config: &GlobalConfig, mut calls: Vec<ToolCall>) -> Result<Vec<ToolResult>> {
    let mut output = vec![];
    if calls.is_empty() {
        return Ok(output);
    }
    calls = ToolCall::dedup(calls);
    if calls.is_empty() {
        bail!("The request was aborted because an infinite loop of function calls was detected.")
    }
    let mut is_all_null = true;
    for call in calls {
        let mut result = call.eval(config)?;
        if result.is_null() {
            result = json!("DONE");
        } else {
            is_all_null = false;
        }
        output.push(ToolResult::new(call, result));
    }
    if is_all_null {
        output = vec![];
    }
    Ok(output)
}

#[derive(Debug, Clone, Deserialize, Serialize)]

View on GitHub (pinned to 82976d349a)