{"record":{"id":"94adb7bc7e2ae8c2","repo":"spring-projects/spring-ai","slug":"request-must-not-be-null","errorCode":null,"errorMessage":"Request must not be null","messagePattern":"Request 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/complete/SyncMcpCompleteMethodCallback.java","lineNumber":66,"sourceCode":"\t\tthis.validateMethod(this.method);\n\t}\n\n\t/**\n\t * Apply the callback to the given exchange and request.\n\t * <p>\n\t * This method builds the arguments for the method call, invokes the method, and\n\t * converts the result to a CompleteResult.\n\t * @param exchange The server exchange, may be null if the method doesn't require it\n\t * @param request The complete request, must not be null\n\t * @return The complete result\n\t * @throws McpCompleteMethodException if there is an error invoking the complete\n\t * method\n\t * @throws IllegalArgumentException if the request is null\n\t */\n\t@Override\n\tpublic CompleteResult apply(McpSyncServerExchange exchange, CompleteRequest request) {\n\t\tif (request == null) {\n\t\t\tthrow new IllegalArgumentException(\"Request 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, exchange, request);\n\n\t\t\t// Invoke the method\n\t\t\tthis.method.setAccessible(true);\n\t\t\tObject result = this.method.invoke(this.bean, args);\n\n\t\t\t// Convert the result to a CompleteResult\n\t\t\treturn convertToCompleteResult(result);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new McpCompleteMethodException(\"Error invoking complete method: \" + this.method.getName(), e);\n\t\t}\n\t}\n","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/complete/SyncMcpCompleteMethodCallback.java#L48-L84","documentation":"SyncMcpCompleteMethodCallback.apply() guards its entry point: if the CompleteRequest argument is null, an IllegalArgumentException is thrown immediately before any method invocation. The library treats a missing completion request as a programming/integration error rather than an empty-completion case.","triggerScenarios":"Calling server registration callbacks or apply() directly with a null CompleteRequest, e.g. a custom transport or test harness passing null instead of a CompleteRequest(argumentName, argumentValue).","commonSituations":"Unit tests invoking the callback with null; hand-rolled MCP transport layers that skip null checks; mocking frameworks returning null for the request parameter.","solutions":["Construct a real CompleteRequest before calling apply(): new CompleteRequest(argumentName, argumentValue)","Fix the transport/adapter layer to never pass null requests; skip or reject null upstream","In tests, pass a mock or stub CompleteRequest instead of null"],"exampleFix":"// before\ncallback.apply(exchange, null);\n// after\ncallback.apply(exchange, new CompleteRequest(\"topic\", \"sp\"));","handlingStrategy":"validation","validationCode":"if (request == null || request.name() == null) {\n    throw new IllegalArgumentException(\"CompleteRequest and its name must be set before calling apply\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return callback.apply(exchange, request);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Null or invalid complete request: {}\", e.getMessage());\n    return new CompleteResult(new CompleteCompletion(List.of(), 0, false));\n}","preventionTips":["Always construct CompleteRequest with a non-null argument name/value from the client's completion request","In transports/adapters, reject or skip null requests before dispatching to callbacks","In tests, use real or stubbed CompleteRequest objects, never null","Add an assertion layer in custom MCP transport code"],"tags":["mcp","completion","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"}