agentscope-ai/agentscope · error · ExceptionGroup
One or more tool calls raised an exception
Error message
One or more tool calls raised an exception
What it means
Raised as an ExceptionGroup when one or more concurrently executing tool call tasks raised an exception. The agent runs tool calls in parallel (e.g. via parallel tool execution mode); after all tasks finish, any exceptions collected are bundled and re-raised together so no failure is silently dropped.
Source
Thrown at src/agentscope/agent/_agent.py:2120
event = queue.get_nowait()
except asyncio.QueueEmpty:
break
if event is sentinel:
continue
yield event
# Consume the cancel so this generator returns normally. The
# caller relies on the flushed ``ToolResultEndEvent(state=
# INTERRUPTED)`` events, not on the exception, to detect the
# interruption — mirroring the event-based propagation used by
# :meth:`_execute_sequential_tool_calls`.
asyncio.current_task().uncancel()
return
# All tasks are done at this point; collect and re-raise exceptions.
results = await gather_task
exceptions = [r for r in results if isinstance(r, Exception)]
if exceptions:
raise ExceptionGroup(
"One or more tool calls raised an exception",
exceptions,
)
async def _into_queue(
self,
tool_call: ToolCallBlock,
queue: Queue,
kept_rules: list[PermissionRule] | None = None,
) -> None:
"""Execute a single tool call and forward every event into *queue*.
Args:
tool_call (`ToolCallBlock`):
The tool call to execute.
queue (`Queue`):
The shared async queue that collects events from all
concurrent workers.View on GitHub (pinned to e90f1c7592)
Solutions
- Inspect exc.exceptions (the ExceptionGroup members) to find which tool actually failed and why
- Wrap individual tool functions so they return error results instead of raising, letting the agent see tool errors as observations
- Fix the root-cause exception in the failing tool (check its stack trace inside the group)
- Switch to sequential tool execution if partial failures should abort cleanly
Example fix
// before
def my_tool(path: str) -> str:
with open(path) as f: # raises, bubbles into ExceptionGroup
return f.read()
// after
def my_tool(path: str) -> str:
try:
with open(path) as f:
return f.read()
except OSError as e:
return f"Error reading {path}: {e}" # returned as tool result Defensive patterns
Strategy: try-catch
Type guard
def is_tool_exception_group(exc: BaseException) -> bool:
return isinstance(exc, ExceptionGroup) and any(
isinstance(e, Exception) for e in exc.exceptions
) Try / catch
try:
reply = await agent.run(msg)
except ExceptionGroup as eg:
for sub in eg.exceptions:
logger.error("tool call failed: %r", sub) Prevention
- Make tool functions return error strings instead of raising
- Wrap risky I/O inside tool implementations with try/except
- Test each tool standalone before enabling parallel execution
When it happens
Trigger: Agent configured with concurrent/parallel tool execution and multiple tool calls in one reply block where at least one tool raises (e.g. a tool function throws, a tool's internal API call fails, or input processing fails inside the task).
Common situations: Custom tools that perform network or file I/O failing intermittently under concurrency; a buggy third-party tool raising on edge-case inputs; tools with unvalidated assumptions running in parallel mode.
Related errors
- Input validation failed for tool '{tool_call.name}': {e.mess
- Session {session_id!r} already has an active chat run in thi
- Invalid permission decision behavior: {decision.behavior}
- Model call failed after retries, but no exception was raised
- The injection template must contain the '{runtime_state}' pl
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/a33cbd1eb6b61b69.
Report an issue: GitHub.