{"record":{"id":"42a34830a2e1db87","repo":"spring-projects/spring-ai","slug":"method-must-not-be-null-42a348","errorCode":null,"errorMessage":"Method must not be null","messagePattern":"Method must not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/logging/AbstractMcpLoggingMethodCallback.java","lineNumber":68,"sourceCode":"\t\tAssert.notNull(bean, \"Bean can't be null!\");\n\n\t\tthis.method = method;\n\t\tthis.bean = bean;\n\t\tthis.validateMethod(this.method);\n\t}\n\n\t/**\n\t * Validates that the method signature is compatible with the logging consumer\n\t * callback.\n\t * <p>\n\t * This method checks that the return type is valid and that the parameters match the\n\t * expected pattern.\n\t * @param method The method to validate\n\t * @throws IllegalArgumentException if the method signature is not compatible\n\t */\n\tprotected void validateMethod(Method method) {\n\t\tif (method == null) {\n\t\t\tthrow new IllegalArgumentException(\"Method must not be null\");\n\t\t}\n\n\t\tthis.validateReturnType(method);\n\t\tthis.validateParameters(method);\n\t}\n\n\t/**\n\t * Validates that the method return type is compatible with the logging consumer\n\t * callback. This method should be implemented by subclasses to handle specific return\n\t * type validation.\n\t * @param method The method to validate\n\t * @throws IllegalArgumentException if the return type is not compatible\n\t */\n\tprotected abstract void validateReturnType(Method method);\n\n\t/**\n\t * Validates method parameters. This method provides common validation logic and\n\t * delegates exchange type checking to subclasses.","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/logging/AbstractMcpLoggingMethodCallback.java#L50-L86","documentation":"AbstractMcpLoggingMethodCallback.validateMethod() rejects a null Method reference before validating return type and parameters. A logging callback cannot be constructed without a concrete @McpLogging-annotated method to invoke. This is a fail-fast guard, usually reached through subclass builders (e.g. AbstractMcpPromptListChangedMethodCallback-style construction paths).","triggerScenarios":"Passing null as the method argument when constructing a logging method callback directly or via a builder that does not set the method before build().","commonSituations":"Programmatic callback registration where the method is looked up reflectively and the lookup returns null; a builder's method(...) setter never called before build().","solutions":["Ensure the Method reference passed to the callback constructor/builder is non-null","Fix reflective lookup (getDeclaredMethod/getMethod) so it resolves the @McpLogging method","Call method(...) on the builder before build()"],"exampleFix":"// before\nnew SyncMcpLoggingMethodCallback.Builder().bean(handler).build();\n// after\nMethod m = handler.getClass().getDeclaredMethod(\"onLog\", LoggingMessageNotification.class);\nnew SyncMcpLoggingMethodCallback.Builder().method(m).bean(handler).build();","handlingStrategy":"validation","validationCode":"Method m = resolveLoggingMethod(handler); // must not return null\nif (m == null) { throw new IllegalStateException(\"@McpLogging method not found on \" + handler.getClass()); }","typeGuard":"static boolean isResolvable(Class<?> handler, String name, Class<?>... params) {\n    try { return handler.getDeclaredMethod(name, params) != null; }\n    catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":null,"preventionTips":["Check reflective lookups for null before constructing callbacks","Always call method(...) on the builder before build()","Fail fast at startup if an expected @McpLogging method cannot be resolved"],"tags":["mcp","logging","null-check","java"],"backgroundTag":"null-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"}