{"record":{"id":"bc29be6ea214d15e","repo":"spring-projects/spring-ai","slug":"method-must-have-void-return-type-bc29be","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/logging/SyncMcpLoggingMethodCallback.java","lineNumber":83,"sourceCode":"\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new McpLoggingConsumerMethodException(\n\t\t\t\t\t\"Error invoking logging 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 logging consumer\n\t * 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 SyncMcpLoggingConsumerMethodCallback instances.\n\t * <p>\n\t * This builder provides a fluent API for constructing\n\t * SyncMcpLoggingConsumerMethodCallback 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/logging/SyncMcpLoggingMethodCallback.java#L65-L101","documentation":"SyncMcpLoggingMethodCallback.validateReturnType requires the annotated sync logging consumer method to return void; any other return type triggers this IllegalArgumentException at registration, naming the method, declaring class, and actual return type. Sync consumers are fire-and-forget and cannot return values to the framework.","triggerScenarios":"Registering a method like boolean handleLog(LoggingMessageNotification n) or LoggingMessageNotification handleLog(...) with the sync MCP logging annotation; the callback constructor calls validateMethod and throws immediately.","commonSituations":"Reusing an existing method that returns a value as a logging consumer; porting an async Mono<Void> handler to the sync annotation without stripping the return; IDE auto-generated stubs returning Object.","solutions":["Change the method to return void.","If you need the async variant, use Mono<Void> with the async annotation/callback instead.","Extract the logic into a void method and keep the value-returning method separate.","Discard the return value explicitly by assigning to a local variable inside a void wrapper method."],"exampleFix":"// before\npublic boolean handleLog(LoggingMessageNotification n) { log(n); return true; }\n// after\npublic void handleLog(LoggingMessageNotification n) { log(n); }","handlingStrategy":"validation","validationCode":"if (handlerMethod.getReturnType() != void.class) {\n    throw new IllegalStateException(\"Sync @McpLogging handler must return void: \" + handlerMethod);\n}","typeGuard":null,"tryCatchPattern":"try {\n    registry.registerSyncLogging(bean, method);\n} catch (IllegalArgumentException e) {\n    logger.error(\"Sync logging handler must be void: {}\", e.getMessage());\n}","preventionTips":["Use void return for sync handlers, Mono<Void> only for async","Strip return values when porting async handlers to sync","Check signatures whenever refactoring handler methods"],"tags":["mcp","validation","return-type","java"],"backgroundTag":"type-mismatch","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"}