spring-projects/spring-ai · error · ToolExecutionException
Error calling tool:
Error message
Error calling tool:
What it means
SyncMcpToolCallback.call() wraps any error reported by the remote MCP server's tool response into a ToolExecutionException. MCP tools can return a CallToolResult with isError()==true while the transport call itself succeeded; the library treats that as a failed execution and surfaces the server-provided content as the message. The text after 'Error calling tool: ' is the server's own error description.
Source
Thrown at mcp/common/src/main/java/org/springframework/ai/mcp/SyncMcpToolCallback.java:154
catch (McpError ex) {
// A protocol-level error indicates the tool invocation itself failed and
// must not be conveyed to the model. Rethrow it as a hard failure, mirroring
// how @Tool treats checked exceptions and Errors. Since the tool calling
// manager only handles ToolExecutionException, this bubbles up and fails the
// model interaction.
logger.error("Protocol error while calling tool: ", ex);
throw ex;
}
catch (Exception ex) {
logger.error("Exception while tool calling: ", ex);
throw new ToolExecutionException(this.getToolDefinition(), ex);
}
if (response.isError() != null && response.isError()) {
if (logger.isErrorEnabled()) {
logger.error("Error calling tool: " + response.content());
}
throw new ToolExecutionException(this.getToolDefinition(),
new IllegalStateException("Error calling tool: " + response.content()));
}
return jsonHelper.toJson(response.content());
}
/**
* Creates a builder for constructing {@code SyncMcpToolCallback} instances.
* @return a new builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Builder for {@code SyncMcpToolCallback} instances.
*/
public static final class Builder {
View on GitHub (pinned to 98a7beda4f)
Solutions
- Read the cause message (the server content) and correct the tool arguments accordingly
- Re-list tools from the MCP server and confirm the tool name and input schema still match what your code sends
- Check the MCP server logs for the underlying exception inside the tool implementation
- Retry after fixing input or restarting/repairing the MCP server
Example fix
// before
String result = toolCallback.call(argumentsJson, toolContext);
// after
try {
String result = toolCallback.call(argumentsJson, toolContext);
} catch (ToolExecutionException e) {
String serverError = e.getCause().getMessage(); // e.g. "Error calling tool: Invalid arguments: missing 'city'"
throw new IllegalStateException("Tool " + e.getToolDefinition().name() + " failed: " + serverError, e);
} Defensive patterns
Strategy: try-catch
Validate before calling
ToolDefinition def = toolCallback.getToolDefinition(); JsonSchemaValidator.validateOrThrow(def.inputSchema(), argumentsJson); // fail fast on client side // also: ensure def.name() still exists in a fresh listTools() result from the server
Type guard
boolean isErrorResult(CallToolResult r) { return r != null && Boolean.TRUE.equals(r.isError()); } Try / catch
try {
return toolCallback.call(inputJson, toolContext);
} catch (ToolExecutionException e) {
String serverMsg = e.getCause() != null ? e.getCause().getMessage() : "";
throw new IllegalStateException("MCP tool call failed: " + serverMsg, e);
} Prevention
- Validate arguments against the tool's inputSchema before invoking
- Confirm tool name/schema via listTools after any server upgrade
- Capture and log the server error content embedded in the exception cause
- Run in try-catch so a protocol-level tool error doesn't crash the chat pipeline
When it happens
Trigger: Calling a sync MCP tool via SyncMcpToolCallback.call(String functionInput, ToolContext) where the McpSyncClient.callTool(...) result has isError()==true (server rejected args, tool threw, or tool name unknown on the server).
Common situations: Sending tool arguments that fail the server-side JSON schema validation; the remote tool implementation raised an exception whose message the server returned as content; the tool was renamed/removed on the server between listing and calling; MCP server version exposes an incompatible tool schema.
Related errors
- Error calling tool:
- Failed to read stdio connection resource
- SSE connection '<connectionName>' requires a 'url' property.
- Failed to create SSE transport for connection '<connectionNa
- Multiple tools with the same name (%s)
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/39856c710465a357.
Report an issue: GitHub.