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
- Construct a real CompleteRequest before calling apply(): new CompleteRequest(argumentName, argumentValue)
- Fix the transport/adapter layer to never pass null requests; skip or reject null upstream
- 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
- Always construct CompleteRequest with a non-null argument name/value from the client's completion request
- In transports/adapters, reject or skip null requests before dispatching to callbacks
- In tests, use real or stubbed CompleteRequest objects, never null
- Add an assertion layer in custom MCP transport code
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
- Request must not be null
- Either prompt or uri must be provided!
- Method must not be null
- List items must be of type String
- Unsupported return type: {resultType}
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/94adb7bc7e2ae8c2.
Report an issue: GitHub.