spring-projects/spring-ai · error · IllegalArgumentException

Method cannot have more than one @McpProgressToken parameter

Error message

Method cannot have more than one @McpProgressToken parameter: 

What it means

A completion method may accept at most one parameter annotated with @McpProgressToken (the progress token injected by the framework). validateParameters() throws this IllegalArgumentException when it encounters a second @McpProgressToken-annotated parameter, at registration time.

Source

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

							+ nonSpecialParamCount + " parameters");
		}

		// Check parameter types
		boolean hasExchangeParam = false;
		boolean hasTransportContext = false;
		boolean hasRequestParam = false;
		boolean hasArgumentParam = false;
		boolean hasProgressTokenParam = false;
		boolean hasMetaParam = false;
		boolean hasRequestContextParam = false;

		for (Parameter param : parameters) {
			Class<?> paramType = param.getType();

			// Skip @McpProgressToken annotated parameters from validation
			if (param.isAnnotationPresent(McpProgressToken.class)) {
				if (hasProgressTokenParam) {
					throw new IllegalArgumentException("Method cannot have more than one @McpProgressToken parameter: "
							+ method.getName() + " in " + method.getDeclaringClass().getName());
				}
				hasProgressTokenParam = true;
				continue;
			}

			// Skip McpMeta parameters from validation
			if (McpMeta.class.isAssignableFrom(paramType)) {
				if (hasMetaParam) {
					throw new IllegalArgumentException("Method cannot have more than one McpMeta parameter: "
							+ method.getName() + " in " + method.getDeclaringClass().getName());
				}
				hasMetaParam = true;
				continue;
			}

			if (McpSyncRequestContext.class.isAssignableFrom(paramType)) {
				if (hasRequestContextParam) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Keep exactly one @McpProgressToken-annotated parameter (or none).
  2. Remove the duplicate annotation/parameter.
  3. If multiple values are needed, read them from the request context instead.

Example fix

// before
public void complete(String value, @McpProgressToken String t1, @McpProgressToken String t2) { }
// after
public void complete(String value, @McpProgressToken String token) { }
Defensive patterns

Strategy: validation

Validate before calling

long tokens = Arrays.stream(method.getParameters())
    .filter(p -> p.isAnnotationPresent(McpProgressToken.class)).count();
if (tokens > 1) throw new IllegalStateException("duplicate @McpProgressToken in " + method.getName());

Prevention

When it happens

Trigger: Declaring two or more parameters annotated @McpProgressToken on a single @McpComplete-annotated method.

Common situations: Copy-paste duplication of a parameter line; misunderstanding the annotation as per-argument rather than a singleton injection; merge conflicts leaving duplicated parameters.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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