spring-projects/spring-ai · error · IllegalArgumentException

ToolContext is required by the method as an argument

Error message

ToolContext is required by the method as an argument

What it means

MethodToolCallback.call() validates that if the target @Tool method declares a ToolContext parameter, a non-empty ToolContext was actually provided at call time. If the method accepts ToolContext but the caller passed null or an empty context, it throws an IllegalArgumentException, because the tool would otherwise run without required contextual data.

Solutions

  1. Pass a non-empty ToolContext when calling: new ToolCallback invocation with .toolContext(Map.of("key", value)) or methodContext on ChatClient.
  2. If context is genuinely optional, remove the ToolContext parameter from the @Tool method and use closure/field state instead.
  3. Guard call sites with a check that the context map is non-empty before invoking the tool.

Example fix

// before
String result = toolCallback.call("{\"q\":\"hi\"}"); // no context, method requires ToolContext
// after
String result = toolCallback.call("{\"q\":\"hi\"}", new ToolContext(Map.of("tenantId", "acme")));
Defensive patterns

Strategy: validation

Validate before calling

if (toolContext == null || toolContext.getContext().isEmpty()) {
    throw new IllegalArgumentException("This tool requires a non-empty ToolContext");
}

Type guard

boolean contextSatisfied = toolContext != null && !toolContext.getContext().isEmpty();

Try / catch

try { result = toolCallback.call(input, toolContext); } catch (IllegalArgumentException e) { if (e.getMessage().contains("ToolContext is required")) { toolContext = new ToolContext(defaultContext()); result = toolCallback.call(input, toolContext); } else throw e; }

Prevention

When it happens

Trigger: Invoking toolCallbacks with a null toolContext or new ToolContext(Map.of()) when the @Tool method signature is e.g. void run(String q, ToolContext ctx); calling the tool directly via chatClient tools without passing context.

Common situations: Tools designed for tenant/user IDs passed via ToolContext being invoked from tests or from ChatClient calls that omit .toolContext(...); framework-internal calls that never supply context.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at spring-ai-model/src/main/java/org/springframework/ai/tool/method/MethodToolCallback.java:130

		Object[] methodArguments = this.buildMethodArguments(toolArguments, toolContext);

		Object result = this.callMethod(methodArguments);

		if (logger.isDebugEnabled()) {
			logger.debug("Successful execution of tool: " + this.toolDefinition.name());
		}

		Type returnType = this.toolMethod.getGenericReturnType();

		return this.toolCallResultConverter.convert(result, returnType);
	}

	private void validateToolContextSupport(@Nullable ToolContext toolContext) {
		var isNonEmptyToolContextProvided = toolContext != null && !CollectionUtils.isEmpty(toolContext.getContext());
		var isToolContextAcceptedByMethod = Stream.of(this.toolMethod.getParameterTypes())
			.anyMatch(type -> ClassUtils.isAssignable(ToolContext.class, type));
		if (isToolContextAcceptedByMethod && !isNonEmptyToolContextProvided) {
			throw new IllegalArgumentException("ToolContext is required by the method as an argument");
		}
	}

	private @Nullable Map<String, Object> extractToolArguments(String toolInput) {
		try {
			return jsonHelper.fromJson(toolInput, new ParameterizedTypeReference<>() {
			});
		}
		catch (Exception ex) {
			logger.warn("Conversion from JSON failed", ex);
			Throwable cause = (ex.getCause() instanceof JacksonException) ? ex.getCause() : ex;
			throw new ToolExecutionException(this.getToolDefinition(), cause);
		}
	}

	// Based on the implementation in MethodToolCallback.
	@SuppressWarnings("null")
	private Object[] buildMethodArguments(Map<String, Object> toolInputArguments, @Nullable ToolContext toolContext) {

View on GitHub (pinned to 98a7beda4f)