{"record":{"id":"8467ce334c7cef65","repo":"spring-projects/spring-ai","slug":"method-must-not-be-null-8467ce","errorCode":null,"errorMessage":"Method must not be null","messagePattern":"Method must not be null","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/tool/AbstractMcpToolListChangedMethodCallback.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 tool list changed\n\t * consumer 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 tool list changed\n\t * consumer callback. This method should be implemented by subclasses to handle\n\t * specific return 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.\n\t * @param method The method to validate","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/changed/tool/AbstractMcpToolListChangedMethodCallback.java#L50-L86","documentation":"AbstractMcpToolListChangedMethodCallback.validateMethod rejects a null java.lang.reflect.Method before checking its signature. The callback cannot dispatch tool-list-changed notifications without a reflective Method target, so the library fails fast during construction/validation rather than at notification time.","triggerScenarios":"Building an AbstractMcpToolListChangedMethodCallback (or subclass, e.g. via the builder or the AbstractMcpPromptListChangedMethodCallback reuse path) with method = null, or calling validateMethod(null) directly from subclass code.","commonSituations":"Reflection failures upstream — e.g. Class.getMethod/getDeclaredMethod throwing NoSuchMethodException being swallowed and null propagated, bean classes that lost the handler method after a rename/refactor, or builder code assembling the callback before resolving the method.","solutions":["Ensure the Method passed to the callback or builder is non-null before construction: this.getClass().getDeclaredMethod(\"handlerName\", List.class)","Fix the method lookup — verify the handler method name and parameter types (exactly one List<McpSchema.Tool>) match the bean class","If using the builder, call .method(m) with a resolved Method before .build(); check that the reflection lookup did not swallow a NoSuchMethodException"],"exampleFix":"// before\nMethod m = beanClass.getMethod(\"onToolListChanged\"); // throws NoSuchMethodException, m may be unset\nbuilder.method(m).build();\n// after\nMethod m;\ntry { m = beanClass.getMethod(\"onToolListChanged\", List.class); }\ncatch (NoSuchMethodException e) { throw new IllegalStateException(\"Handler method missing\", e); }\nbuilder.method(m).build();","handlingStrategy":"validation","validationCode":"java.util.Objects.requireNonNull(method, \"method must be resolved before building the callback\");","typeGuard":"static boolean methodResolved(java.lang.reflect.Method m) { return m != null; }","tryCatchPattern":"try { builder.method(method).build(); } catch (IllegalArgumentException e) { log.error(\"Callback validation failed: {}\", e.getMessage()); }","preventionTips":["Resolve the Method with getDeclaredMethod/getMethod and propagate NoSuchMethodException instead of swallowing it","Check that the handler method still exists after refactors (compile-time annotation processing helps)","Log the target class/method name at registration for debuggability"],"tags":["java","reflection","null","validation"],"backgroundTag":"null-argument","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"}