{"record":{"id":"b80eeb01836107e4","repo":"spring-projects/spring-ai","slug":"method-must-not-be-null-b80eeb","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/elicitation/AbstractMcpElicitationMethodCallback.java","lineNumber":66,"sourceCode":"\t\tAssert.notNull(method, \"Method can't be null!\");\n\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 elicitation 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 elicitation callback.\n\t * This method should be implemented by subclasses to handle specific return type\n\t * 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":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/elicitation/AbstractMcpElicitationMethodCallback.java#L48-L84","documentation":"AbstractMcpElicitationMethodCallback.validateMethod throws this IllegalArgumentException when the Method passed to an elicitation callback constructor is null. The callback needs a concrete reflected method to validate and later invoke when the client responds to an elicitation.","triggerScenarios":"Building the callback with a null Method, e.g. a lookup by annotation/name that fails silently and returns null before calling new SyncMcpElicitationMethodCallback(bean, null, ...).","commonSituations":"Custom annotation scanners that use getDeclaredMethod with a misspelled name or wrong parameter types (throwing NoSuchMethodException swallowed elsewhere), leading to a null Method handoff.","solutions":["Pass a valid non-null Method instance from your scanner to the callback constructor","Fix the method lookup: verify the exact method name and parameter types in getDeclaredMethod","Log/handle NoSuchMethodException at the lookup site instead of propagating null"],"exampleFix":"// before\nMethod m = null; // lookup failed\nnew SyncMcpElicitationMethodCallback(bean, m, \"id\");\n// after\nMethod m = bean.getClass().getDeclaredMethod(\"onElicit\", ElicitRequest.class);\nnew SyncMcpElicitationMethodCallback(bean, m, \"id\");","handlingStrategy":"validation","validationCode":"Method m = lookupElicitationMethod(bean, elicitId);\nif (m == null) throw new IllegalStateException(\"no @McpElicitation method found for id \" + elicitId);","typeGuard":"static Optional<Method> findElicitMethod(Object bean) {\n    return Arrays.stream(bean.getClass().getDeclaredMethods())\n        .filter(m -> m.isAnnotationPresent(McpElicitation.class))\n        .findFirst();\n}","tryCatchPattern":"try { new SyncMcpElicitationMethodCallback(bean, method, elicitId); }\ncatch (IllegalArgumentException e) { log.error(\"elicitation callback construction failed: {}\", e.getMessage()); throw e; }","preventionTips":["Never hand a null Method to the callback constructor","Handle NoSuchMethodException at the lookup site instead of defaulting to null","Use annotation scanning (findFirst over getDeclaredMethods) rather than fragile name-based lookups"],"tags":["java","mcp","elicitation","null-check"],"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"}