{"record":{"id":"953f3f8c6e216997","repo":"spring-projects/spring-ai","slug":"parameter-must-be-of-type-list-mcpschema-prompt","errorCode":null,"errorMessage":"Parameter must be of type List<McpSchema.Prompt>: ","messagePattern":"Parameter must be of type List<McpSchema\\.Prompt>: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/prompt/AbstractMcpPromptListChangedMethodCallback.java","lineNumber":102,"sourceCode":"\t/**\n\t * Validates method parameters. This method provides common validation logic.\n\t * @param method The method to validate\n\t * @throws IllegalArgumentException if the parameters are not compatible\n\t */\n\tprotected void validateParameters(Method method) {\n\t\tParameter[] parameters = method.getParameters();\n\n\t\t// Check parameter count - must have exactly 1 parameter\n\t\tif (parameters.length != 1) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Method must have exactly 1 parameter (List<McpSchema.Prompt>): \" + method.getName() + \" in \"\n\t\t\t\t\t\t\t+ method.getDeclaringClass().getName() + \" has \" + parameters.length + \" parameters\");\n\t\t}\n\n\t\t// Check parameter type - must be List<McpSchema.Prompt>\n\t\tClass<?> paramType = parameters[0].getType();\n\t\tif (!List.class.isAssignableFrom(paramType)) {\n\t\t\tthrow new IllegalArgumentException(\"Parameter must be of type List<McpSchema.Prompt>: \" + method.getName()\n\t\t\t\t\t+ \" in \" + method.getDeclaringClass().getName() + \" has parameter of type \" + paramType.getName());\n\t\t}\n\t}\n\n\t/**\n\t * Builds the arguments array for invoking the method.\n\t * <p>\n\t * This method constructs an array of arguments based on the method's parameter types\n\t * and the available values.\n\t * @param method The method to build arguments for\n\t * @param exchange The server exchange\n\t * @param updatedPrompts The updated list of prompts\n\t * @return An array of arguments for the method invocation\n\t */\n\tprotected Object[] buildArgs(Method method, Object exchange, List<McpSchema.Prompt> updatedPrompts) {\n\t\tParameter[] parameters = method.getParameters();\n\t\tObject[] args = new Object[parameters.length];\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/prompt/AbstractMcpPromptListChangedMethodCallback.java#L84-L120","documentation":"validateParameters also checks the single parameter's type: it must be assignable from List (the prompt list). A handler whose sole parameter is a different type (e.g. List<String>, Prompt[], or a non-list custom type) cannot receive List<McpSchema.Prompt> and is rejected.","triggerScenarios":"Registering a one-parameter handler whose parameter is not a List (e.g. a raw array, a String, or a list of the wrong element type such as List<String>).","commonSituations":"Developers guess the callback signature instead of copying the documented one; same-named custom Prompt classes shadowing the expected McpSchema.Prompt type.","solutions":["Declare the parameter as List<McpSchema.Prompt> (or a subtype/assignable List type)","Fix the import so the parameter uses the MCP spec McpSchema.Prompt, not a locally defined Prompt class","Prefer the fully typed List<McpSchema.Prompt> over a raw List even though a raw List passes the check"],"exampleFix":"// before\npublic void onPromptListChanged(List<String> promptNames) { ... }\n// after\npublic void onPromptListChanged(List<McpSchema.Prompt> prompts) { ... }","handlingStrategy":"validation","validationCode":"if (method.getParameterCount() == 1 && !List.class.isAssignableFrom(method.getParameterTypes()[0])) { throw new IllegalArgumentException(\"Parameter must be List<McpSchema.Prompt>\"); }","typeGuard":"boolean paramIsPromptList = m.getParameterCount() == 1 && List.class.isAssignableFrom(m.getParameterTypes()[0]);","tryCatchPattern":"try { registerCallback(method); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Parameter must be of type\")) { log.error(\"Fix handler to accept List<McpSchema.Prompt>\"); } throw e; }","preventionTips":["Import McpSchema.Prompt from the MCP spec package, not a custom class with the same name","Keep generics explicit: List<McpSchema.Prompt>, not raw or wrong-element lists","Validate handler signatures in integration tests at startup"],"tags":["mcp","reflection","method-signature","type-mismatch"],"backgroundTag":"type-mismatch","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"}