{"record":{"id":"eeaa01581668175e","repo":"spring-projects/spring-ai","slug":"method-cannot-have-more-than-one-mcpprogresstoken","errorCode":null,"errorMessage":"Method cannot have more than one @McpProgressToken parameter: ","messagePattern":"Method cannot have more than one @McpProgressToken parameter: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java","lineNumber":183,"sourceCode":"\t\t\t\t\t\t\t+ nonSpecialParamCount + \" parameters\");\n\t\t}\n\n\t\t// Check parameter types\n\t\tboolean hasExchangeParam = false;\n\t\tboolean hasTransportContext = false;\n\t\tboolean hasRequestParam = false;\n\t\tboolean hasArgumentParam = false;\n\t\tboolean hasProgressTokenParam = false;\n\t\tboolean hasMetaParam = false;\n\t\tboolean hasRequestContextParam = false;\n\n\t\tfor (Parameter param : parameters) {\n\t\t\tClass<?> paramType = param.getType();\n\n\t\t\t// Skip @McpProgressToken annotated parameters from validation\n\t\t\tif (param.isAnnotationPresent(McpProgressToken.class)) {\n\t\t\t\tif (hasProgressTokenParam) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Method cannot have more than one @McpProgressToken parameter: \"\n\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\thasProgressTokenParam = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip McpMeta parameters from validation\n\t\t\tif (McpMeta.class.isAssignableFrom(paramType)) {\n\t\t\t\tif (hasMetaParam) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Method cannot have more than one McpMeta parameter: \"\n\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\thasMetaParam = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (McpSyncRequestContext.class.isAssignableFrom(paramType)) {\n\t\t\t\tif (hasRequestContextParam) {","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java#L165-L201","documentation":"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.","triggerScenarios":"Declaring two or more parameters annotated @McpProgressToken on a single @McpComplete-annotated method.","commonSituations":"Copy-paste duplication of a parameter line; misunderstanding the annotation as per-argument rather than a singleton injection; merge conflicts leaving duplicated parameters.","solutions":["Keep exactly one @McpProgressToken-annotated parameter (or none).","Remove the duplicate annotation/parameter.","If multiple values are needed, read them from the request context instead."],"exampleFix":"// before\npublic void complete(String value, @McpProgressToken String t1, @McpProgressToken String t2) { }\n// after\npublic void complete(String value, @McpProgressToken String token) { }","handlingStrategy":"validation","validationCode":"long tokens = Arrays.stream(method.getParameters())\n    .filter(p -> p.isAnnotationPresent(McpProgressToken.class)).count();\nif (tokens > 1) throw new IllegalStateException(\"duplicate @McpProgressToken in \" + method.getName());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use at most one @McpProgressToken parameter per handler.","Watch for duplicated parameters after merges or code generation."],"tags":["mcp","validation","duplicate-parameter","completion"],"backgroundTag":"invalid-argument-value","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}