spring-projects/spring-ai · error · java.lang.IllegalArgumentException

Method cannot have more than one request context parameter

Error message

Method cannot have more than one request context parameter: {method.getName()} in {method.getDeclaringClass().getName()}

What it means

validateParameters() enforces that an @McpPrompt method has at most one request-context parameter. When a parameter is assignable from McpSyncRequestContext, declaring a second context parameter (sync or async) is ambiguous and throws IllegalArgumentException naming the method and declaring class.

Solutions

  1. Remove the duplicate context parameter, keeping exactly one McpSyncRequestContext.
  2. If you need async behavior, remove the sync context entirely and use a single McpAsyncRequestContext with a reactive return type.
  3. Re-check the full parameter list after refactoring to confirm only one context parameter remains.

Example fix

// before
@McpPrompt(name = "p")
public String complete(String q, McpSyncRequestContext c1, McpSyncRequestContext c2) { ... }
// after
@McpPrompt(name = "p")
public String complete(String q, McpSyncRequestContext context) { ... }
Defensive patterns

Strategy: validation

Validate before calling

long ctxParams = Arrays.stream(method.getParameters())
    .filter(p -> McpSyncRequestContext.class.isAssignableFrom(p.getType())
              || McpAsyncRequestContext.class.isAssignableFrom(p.getType())).count();
if (ctxParams > 1) throw new IllegalStateException("Only one request context parameter allowed");

Try / catch

try { registry.register(bean); } catch (IllegalArgumentException e) { log.error("Invalid @McpPrompt signature: {}", e.getMessage()); }

Prevention

When it happens

Trigger: An @McpPrompt method declaring two context parameters, e.g. complete(String q, McpSyncRequestContext c1, McpSyncRequestContext c2), or mixing McpSyncRequestContext with McpAsyncRequestContext.

Common situations: Copy-paste duplication of a context parameter; refactoring from sync to async by adding the async context without removing the sync one; confusion over which context type the framework injects.

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

Appendix: source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AbstractMcpPromptMethodCallback.java:149

							+ 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(
							"Sync complete methods should use McpSyncRequestContext instead of McpAsyncRequestContext parameter: "
									+ method.getName() + " in " + method.getDeclaringClass().getName());
				}
				hasRequestContextParam = true;
			}
			else if (McpAsyncRequestContext.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.isNotReactiveReturnType.test(method)) {
					throw new IllegalArgumentException(
							"Async complete methods should use McpAsyncRequestContext instead of McpSyncRequestContext parameter: "
									+ method.getName() + " in " + method.getDeclaringClass().getName());

View on GitHub (pinned to 98a7beda4f)