spring-projects/spring-ai · error · IllegalArgumentException

Method cannot have more than one McpMeta parameter: {method}

Error message

Method cannot have more than one McpMeta parameter: {method} in {class}

What it means

At most one McpMeta-typed parameter is allowed per completion method; the framework injects request metadata once. validateParameters() throws this IllegalArgumentException if a second McpMeta (or subclass) parameter is found, listing the method and declaring class.

Source

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

		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) {
					throw new IllegalArgumentException("Method cannot have more than one request context parameter: "
							+ method.getName() + " in " + method.getDeclaringClass().getName());
				}
				if (McpPredicates.isReactiveReturnType.test(method)) {
					throw new IllegalArgumentException(
							"Async complete methods should use McpAsyncRequestContext instead of McpSyncRequestContext parameter: "
									+ method.getName() + " in " + method.getDeclaringClass().getName());
				}

				hasRequestContextParam = true;

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Remove the redundant McpMeta parameter, keeping at most one.
  2. If different metadata views are needed, extract fields from the single McpMeta instance in the method body.

Example fix

// before
public void complete(String value, McpMeta meta, McpMeta meta2) { }
// after
public void complete(String value, McpMeta meta) { }
Defensive patterns

Strategy: validation

Validate before calling

long metas = Arrays.stream(method.getParameters())
    .filter(p -> McpMeta.class.isAssignableFrom(p.getType())).count();
if (metas > 1) throw new IllegalStateException("duplicate McpMeta parameter in " + method.getName());

Prevention

When it happens

Trigger: Declaring two parameters assignable to McpMeta on one @McpComplete-annotated method.

Common situations: Adding McpMeta twice while extending an existing handler signature; auto-generated stubs that already include McpMeta being augmented; merge artifacts.

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/2c1b67e063016946. Report an issue: GitHub.