alibaba/spring-ai-alibaba · warning · ToolCancelledException

Tool execution was cancelled

Error message

Tool execution was cancelled

What it means

When the async tool's future completes with a CancellationException (e.g. the CancellationToken was triggered), call() throws ToolCancelledException with message "Tool execution was cancelled". This is a typed signal that the tool was aborted rather than failed.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tool/AsyncToolCallback.java:111

	 * @throws ToolCancelledException if the operation was cancelled
	 */
	@Override
	default String call(String arguments, ToolContext context) {
		try {
			return callAsync(arguments, context).join();
		}
		catch (CompletionException e) {
			Throwable cause = e.getCause();
			if (cause instanceof RuntimeException re) {
				throw re;
			}
			if (cause instanceof Error err) {
				throw err;
			}
			throw new RuntimeException("Async tool execution failed", cause);
		}
		catch (CancellationException e) {
			throw new ToolCancelledException("Tool execution was cancelled", e);
		}
	}

	/**
	 * Returns whether this tool executes asynchronously.
	 * @return true (always async for this interface)
	 */
	default boolean isAsync() {
		return true;
	}

	/**
	 * Returns the timeout duration for this tool execution.
	 * @return the timeout duration, defaults to 5 minutes
	 */
	default Duration getTimeout() {
		return Duration.ofMinutes(5);
	}

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Catch ToolCancelledException specifically and treat it as a normal abort, not an error.
  2. Ensure cancellation tokens are cancelled intentionally; review timeout/cancel call sites.
  3. Make tools check CancellationToken periodically so cancellation is honored promptly.
  4. Log cancellation at info/debug level instead of treating it as a failure.

Example fix

// before
try { result = asyncTool.call(input, token); }
catch (RuntimeException e) { log.error("tool failed", e); }
// after
try { result = asyncTool.call(input, token); }
catch (ToolCancelledException e) { log.info("tool cancelled, aborting gracefully"); return null; }
catch (RuntimeException e) { log.error("tool failed", e); }
Defensive patterns

Strategy: try-catch

Try / catch

try { result = callback.call(input, token); } catch (ToolCancelledException e) { /* graceful abort */ } catch (CancellationException e) { /* already wrapped, unreachable but safe */ }

Prevention

When it happens

Trigger: A CancellationToken passed to the async tool is cancelled while the tool is still running; the underlying future is cancelled() by timeout or upstream abort; the executor cancels the task.

Common situations: User aborts a request mid-tool-call, agent-level timeouts cancelling running tools, cancellation propagation when a graph node is interrupted.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/7df2f18294199a96. Report an issue: GitHub.