{"record":{"id":"85502a5ea22f1554","repo":"spring-projects/spring-ai","slug":"error-invoking-logging-consumer-method","errorCode":null,"errorMessage":"Error invoking logging consumer method: ","messagePattern":"Error invoking logging consumer method: ","errorType":"exception","errorClass":"McpLoggingConsumerMethodException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/logging/SyncMcpLoggingMethodCallback.java","lineNumber":67,"sourceCode":"\t * consumer method\n\t * @throws IllegalArgumentException if the notification is null\n\t */\n\t@Override\n\tpublic void accept(LoggingMessageNotification notification) {\n\t\tif (notification == null) {\n\t\t\tthrow new IllegalArgumentException(\"Notification must not be null\");\n\t\t}\n\n\t\ttry {\n\t\t\t// Build arguments for the method call\n\t\t\tObject[] args = this.buildArgs(this.method, null, notification);\n\n\t\t\t// Invoke the method\n\t\t\tthis.method.setAccessible(true);\n\t\t\tthis.method.invoke(this.bean, args);\n\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}","sourceCodeStart":49,"sourceCodeEnd":85,"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#L49-L85","documentation":"The annotated sync logging consumer method threw while being reflectively invoked. SyncMcpLoggingMethodCallback catches the reflection exception and rethrows it as McpLoggingConsumerMethodException with message 'Error invoking logging consumer method: <methodName>', preserving the original as the cause. This is a wrapper — the real fault is in the user's handler method or argument binding.","triggerScenarios":"The user's @McpLogging method throws any exception (NPE, business error) at runtime; buildArgs supplied arguments incompatible with the method signature causing IllegalArgumentException from Method.invoke; the method is not accessible on the bean.","commonSituations":"Handler assumes non-null fields on the notification that are absent; handler signature expects a different type than LoggingMessageNotification so reflection binding fails; a database/logging backend used inside the handler is down.","solutions":["Inspect the cause chain (getCause()) to find the real exception from the handler method.","Fix the exception inside the annotated consumer method; wrap its risky operations in try-catch if logging must never fail.","Verify the handler's parameter types match exactly what the callback builds (LoggingMessageNotification).","Add logging around the handler body during development to localize the failing statement."],"exampleFix":"// before\npublic void onLog(LoggingMessageNotification n) { store(n.data()); } // NPE when data() is null\n// after\npublic void onLog(LoggingMessageNotification n) {\n    try {\n        if (n != null && n.data() != null) { store(n.data()); }\n    } catch (Exception e) {\n        logger.warn(\"logging handler failed\", e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// verify the handler signature matches before registration\nMethod m = bean.getClass().getMethod(\"onLog\", LoggingMessageNotification.class);","typeGuard":null,"tryCatchPattern":"try {\n    callback.accept(notification);\n} catch (McpLoggingConsumerMethodException e) {\n    logger.error(\"logging consumer \" + e.getMessage() + \" failed\", e.getCause());\n}","preventionTips":["Always log e.getCause(), not just the wrapper message","Make handler bodies defensive against null notification fields","Keep side effects in handlers failure-tolerant (try-catch inside the handler)"],"tags":["mcp","reflection","wrapped-exception","java"],"backgroundTag":"api-request-failed","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"}