{"record":{"id":"1314c7e89a3eeff2","repo":"spring-projects/spring-ai","slug":"method-must-have-void-return-type-1314c7","errorCode":null,"errorMessage":"Method must have void return type: ","messagePattern":"Method must have void return type: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/tool/SyncMcpToolListChangedMethodCallback.java","lineNumber":83,"sourceCode":"\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new McpToolListChangedConsumerMethodException(\n\t\t\t\t\t\"Error invoking tool list changed consumer method: \" + this.method.getName(), e);\n\t\t}\n\t}\n\n\t/**\n\t * Validates that the method return type is compatible with the tool list changed\n\t * consumer callback.\n\t * @param method The method to validate\n\t * @throws IllegalArgumentException if the return type is not compatible\n\t */\n\t@Override\n\tprotected void validateReturnType(Method method) {\n\t\tClass<?> returnType = method.getReturnType();\n\n\t\tif (returnType != void.class) {\n\t\t\tthrow new IllegalArgumentException(\"Method must have void return type: \" + method.getName() + \" in \"\n\t\t\t\t\t+ method.getDeclaringClass().getName() + \" returns \" + returnType.getName());\n\t\t}\n\t}\n\n\t/**\n\t * Create a new builder.\n\t * @return A new builder instance\n\t */\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\t/**\n\t * Builder for creating SyncMcpToolListChangedMethodCallback instances.\n\t * <p>\n\t * This builder provides a fluent API for constructing\n\t * SyncMcpToolListChangedMethodCallback instances with the required parameters.\n\t */","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/tool/SyncMcpToolListChangedMethodCallback.java#L65-L101","documentation":"SyncMcpToolListChangedMethodCallback.validateReturnType() enforces that methods annotated for tool-list-changed callbacks return void, since the consumer is invoked purely for its side effect and there is nowhere to deliver a return value. Any non-void return type is rejected at registration time with an IllegalArgumentException naming the method and its actual return type.","triggerScenarios":"Registering a @McpToolListChanged handler whose declared return type is anything other than void (e.g., boolean, String, List, Mono) via SyncToolListChangedSpecification / the annotation callback builder.","commonSituations":"Copying a handler from an async/reactive variant that returns a publisher; accidentally returning a status value from the consumer; IDE auto-generating a non-void stub.","solutions":["Change the method return type to void.","If you need to signal results, log or store state inside the method instead of returning it.","If you intended reactive semantics, use the async callback variant appropriate for your stack, still honoring the required signature."],"exampleFix":"// before\n@McpToolListChanged(clients = \"client1\")\npublic boolean onToolsChanged(List<McpSchema.Tool> tools) { return true; }\n// after\n@McpToolListChanged(clients = \"client1\")\npublic void onToolsChanged(List<McpSchema.Tool> tools) { LOG.info(\"changed\"); }","handlingStrategy":"validation","validationCode":"if (!method.getReturnType().equals(void.class)) {\n    throw new IllegalStateException(\"@McpToolListChanged method must return void: \" + method.getName());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare tool-list-changed handlers as void.","Never return values from consumer-style callbacks.","Check return types when copying handlers between sync/async variants."],"tags":["mcp","validation","return-type","java"],"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"}