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

  1. Read the cause message (the server content) and correct the tool arguments accordingly
  2. Re-list tools from the MCP server and confirm the tool name and input schema still match what your code sends
  3. Check the MCP server logs for the underlying exception inside the tool implementation
  4. 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

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


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/39856c710465a357. Report an issue: GitHub.