{"record":{"id":"b8a069782fe4b1b8","repo":"spring-projects/spring-ai","slug":"method-cannot-have-more-than-one-getpromptrequest","errorCode":null,"errorMessage":"Method cannot have more than one GetPromptRequest parameter: {method.getName()} in {method.getDeclaringClass().getName()}","messagePattern":"Method cannot have more than one GetPromptRequest parameter: (.+?) in (.+?)","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AbstractMcpPromptMethodCallback.java","lineNumber":180,"sourceCode":"\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\tif (McpPredicates.isNotReactiveReturnType.test(method)) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"Async complete methods should use McpAsyncRequestContext instead of McpSyncRequestContext parameter: \"\n\t\t\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\thasRequestContextParam = true;\n\t\t\t}\n\t\t\telse if (isSupportedExchangeOrContextType(paramType)) {\n\t\t\t\tif (hasExchangeParam) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Method cannot have more than one exchange parameter: \"\n\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\thasExchangeParam = true;\n\t\t\t}\n\t\t\telse if (GetPromptRequest.class.isAssignableFrom(paramType)) {\n\t\t\t\tif (hasRequestParam) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Method cannot have more than one GetPromptRequest parameter: \"\n\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\thasRequestParam = true;\n\t\t\t}\n\t\t\telse if (Map.class.isAssignableFrom(paramType)) {\n\t\t\t\tif (hasMapParam) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Method cannot have more than one Map parameter: \"\n\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t\t\t}\n\t\t\t\thasMapParam = true;\n\t\t\t}\n\t\t\t// Other parameter types are assumed to be individual arguments\n\t\t}\n\t}\n\n\tprotected abstract Object assignExchangeType(Class<?> paramType, Object exchange);\n\n\t/**","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AbstractMcpPromptMethodCallback.java#L162-L198","documentation":"AbstractMcpPromptMethodCallback.validateParameters enforces at most one GetPromptRequest parameter in a prompt method. If a second parameter assignable to GetPromptRequest is found, registration fails with this IllegalArgumentException, because the callback binds the single incoming GetPromptRequest to only one parameter and a duplicate would be ambiguous.","triggerScenarios":"Registering a prompt method like `myPrompt(GetPromptRequest req1, GetPromptRequest req2)`; the check fires in the `GetPromptRequest.class.isAssignableFrom(paramType)` branch when hasRequestParam is already true.","commonSituations":"Copy-paste when adding a parameter 'for convenience'; refactoring where a wrapper type accidentally extends/implements GetPromptRequest so two parameters both satisfy isAssignableFrom; merging two prompt handlers into one method.","solutions":["Remove the duplicate GetPromptRequest parameter and pass the request data as individual @McpArg parameters or a Map if needed.","If you intended distinct data, declare individual typed parameters (@McpArg String name, int max) instead of a second request object.","Ensure no custom class extending GetPromptRequest is declared alongside a raw GetPromptRequest parameter."],"exampleFix":"// before\n@McpPrompt(name = \"code-review\")\npublic String review(GetPromptRequest request, GetPromptRequest request2) { ... }\n// after\n@McpPrompt(name = \"code-review\")\npublic String review(GetPromptRequest request) { ... }","handlingStrategy":"validation","validationCode":"long reqParams = Arrays.stream(method.getParameters())\n    .map(Parameter::getType)\n    .filter(t -> GetPromptRequest.class.isAssignableFrom(t))\n    .count();\nif (reqParams > 1) throw new IllegalStateException(method + \" declares multiple GetPromptRequest parameters\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use exactly one GetPromptRequest parameter, or prefer individual @McpArg parameters.","Avoid custom classes extending GetPromptRequest in handler signatures.","Write a unit test that builds every prompt callback at context startup."],"tags":["mcp","method-signature","duplicate-parameter","getpromptrequest"],"backgroundTag":"invalid-argument","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}