spring-projects/spring-ai · error · java.lang.IllegalArgumentException
Method must have either 1 parameter (ProgressNotification) o
Error message
Method must have either 1 parameter (ProgressNotification) or 3 parameters (Double, String, String): {method.getName()} in {method.getDeclaringClass().getName()} has {parameters.length} parameters What it means
Progress handler methods must take exactly one parameter (a ProgressNotification) or exactly three parameters (Double progress, String total/progressToken, String message). Any other parameter count is rejected at registration with this IllegalArgumentException. Note the message template uses literal {…} placeholders that are not interpolated — the actual counts are appended after the colon.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/progress/AbstractMcpProgressMethodCallback.java:93
* This method should be implemented by subclasses to handle specific return type
* validation.
* @param method The method to validate
* @throws IllegalArgumentException if the return type is not compatible
*/
protected abstract void validateReturnType(Method method);
/**
* Validates method parameters. This method provides common validation logic and
* delegates exchange type checking to subclasses.
* @param method The method to validate
* @throws IllegalArgumentException if the parameters are not compatible
*/
protected void validateParameters(Method method) {
Parameter[] parameters = method.getParameters();
// Check parameter count - must have either 1 or 3 parameters
if (parameters.length != 1 && parameters.length != 3) {
throw new IllegalArgumentException(
"Method must have either 1 parameter (ProgressNotification) or 3 parameters (Double, String, String): "
+ method.getName() + " in " + method.getDeclaringClass().getName() + " has "
+ parameters.length + " parameters");
}
// Check parameter types
if (parameters.length == 1) {
// Single parameter must be ProgressNotification
if (!ProgressNotification.class.isAssignableFrom(parameters[0].getType())) {
throw new IllegalArgumentException("Single parameter must be of type ProgressNotification: "
+ method.getName() + " in " + method.getDeclaringClass().getName() + " has parameter of type "
+ parameters[0].getType().getName());
}
}
else {
// Three parameters must be Double, String, String
if (!Double.class.isAssignableFrom(parameters[0].getType())
&& !double.class.isAssignableFrom(parameters[0].getType())) {View on GitHub (pinned to 98a7beda4f)
Solutions
- Reduce or expand the signature to exactly (ProgressNotification) or (Double, String, String).
- If you need extra context, capture it via constructor/field injection into the bean instead of method parameters.
- Check the parameter order for the three-arg form matches (progress, total, progressToken/message) per the class docs.
- Read the appended text after the colon in the message to see the actual offending parameter count.
Example fix
// before
public void onProgress(ProgressNotification n, McpSession session) { ... }
// after
public void onProgress(ProgressNotification n) { ... } // session held as a bean field Defensive patterns
Strategy: validation
Validate before calling
int n = handlerMethod.getParameterCount();
if (n != 1 && n != 3) {
throw new IllegalStateException("Progress handler must have 1 (ProgressNotification) or 3 (Double,String,String) params: " + handlerMethod);
} Try / catch
try {
registry.registerProgress(bean, method);
} catch (IllegalArgumentException e) {
logger.error("Invalid progress handler arity: {}", e.getMessage());
} Prevention
- Memorize the two allowed signatures: (ProgressNotification) or (Double, String, String)
- Pass extra context via bean fields, not method parameters
- Registration smoke tests catch arity errors at CI time
When it happens
Trigger: Annotating a progress handler with 0, 2, 4+ parameters (e.g. onProgress(ProgressNotification n, String extra)) and registering it; constructor-time validateMethod -> validateParameters throws.
Common situations: Adding a context or session parameter to a handler signature; migrating from a three-arg style to the notification-object style but keeping a leftover second parameter; copy-paste from other MCP callback types with different arity rules.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Method must have exactly 1 parameter (List<McpSchema.Resourc
- Single parameter must be of type ProgressNotification: {meth
- Method must have exactly 1 parameter (List<McpSchema.Prompt>
- Method must have void or Mono<Void> return type:
- Method must have void return type: " + method.getName() + "
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/dacf988991c57b99.
Report an issue: GitHub.