spring-projects/spring-ai · error · IllegalArgumentException

Request must not be null

Error message

Request must not be null

What it means

SyncMcpCompleteMethodCallback.apply() guards its entry point: if the CompleteRequest argument is null, an IllegalArgumentException is thrown immediately before any method invocation. The library treats a missing completion request as a programming/integration error rather than an empty-completion case.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/SyncMcpCompleteMethodCallback.java:66

		this.validateMethod(this.method);
	}

	/**
	 * Apply the callback to the given exchange and request.
	 * <p>
	 * This method builds the arguments for the method call, invokes the method, and
	 * converts the result to a CompleteResult.
	 * @param exchange The server exchange, may be null if the method doesn't require it
	 * @param request The complete request, must not be null
	 * @return The complete result
	 * @throws McpCompleteMethodException if there is an error invoking the complete
	 * method
	 * @throws IllegalArgumentException if the request is null
	 */
	@Override
	public CompleteResult apply(McpSyncServerExchange exchange, CompleteRequest request) {
		if (request == null) {
			throw new IllegalArgumentException("Request must not be null");
		}

		try {
			// Build arguments for the method call
			Object[] args = this.buildArgs(this.method, exchange, request);

			// Invoke the method
			this.method.setAccessible(true);
			Object result = this.method.invoke(this.bean, args);

			// Convert the result to a CompleteResult
			return convertToCompleteResult(result);
		}
		catch (Exception e) {
			throw new McpCompleteMethodException("Error invoking complete method: " + this.method.getName(), e);
		}
	}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Construct a real CompleteRequest before calling apply(): new CompleteRequest(argumentName, argumentValue)
  2. Fix the transport/adapter layer to never pass null requests; skip or reject null upstream
  3. In tests, pass a mock or stub CompleteRequest instead of null

Example fix

// before
callback.apply(exchange, null);
// after
callback.apply(exchange, new CompleteRequest("topic", "sp"));
Defensive patterns

Strategy: validation

Validate before calling

if (request == null || request.name() == null) {
    throw new IllegalArgumentException("CompleteRequest and its name must be set before calling apply");
}

Try / catch

try {
    return callback.apply(exchange, request);
} catch (IllegalArgumentException e) {
    log.warn("Null or invalid complete request: {}", e.getMessage());
    return new CompleteResult(new CompleteCompletion(List.of(), 0, false));
}

Prevention

When it happens

Trigger: Calling server registration callbacks or apply() directly with a null CompleteRequest, e.g. a custom transport or test harness passing null instead of a CompleteRequest(argumentName, argumentValue).

Common situations: Unit tests invoking the callback with null; hand-rolled MCP transport layers that skip null checks; mocking frameworks returning null for the request parameter.

Related errors


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