{"record":{"id":"372c477da23c3863","repo":"spring-projects/spring-ai","slug":"request-must-not-be-null-372c47","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/resource/SyncMcpResourceMethodCallback.java","lineNumber":114,"sourceCode":"\t}\n\n\t/**\n\t * Apply the callback to the given exchange and request.\n\t * <p>\n\t * This method extracts URI variable values from the request URI, builds the arguments\n\t * for the method call, invokes the method, and converts the result to a\n\t * ReadResourceResult.\n\t * @param exchange The server exchange, may be null if the method doesn't require it\n\t * @param request The resource request, must not be null\n\t * @return The resource result\n\t * @throws McpError if there is an error invoking the resource method\n\t * @throws IllegalArgumentException if the request is null or if URI variable\n\t * extraction fails\n\t */\n\t@Override\n\tpublic ReadResourceResult apply(McpSyncServerExchange exchange, ReadResourceRequest 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// Extract URI variable values from the request URI\n\t\t\tMap<String, String> uriVariableValues = this.uriTemplateManager.extractVariableValues(request.uri());\n\n\t\t\t// Verify all URI variables were extracted if URI variables are expected\n\t\t\tif (!this.uriVariables.isEmpty() && uriVariableValues.size() != this.uriVariables.size()) {\n\t\t\t\tthrow new IllegalArgumentException(\"Failed to extract all URI variables from request URI: \"\n\t\t\t\t\t\t+ request.uri() + \". Expected variables: \" + this.uriVariables + \", but found: \"\n\t\t\t\t\t\t+ uriVariableValues.keySet());\n\t\t\t}\n\n\t\t\t// Build arguments for the method call\n\t\t\tObject[] args = this.buildArgs(this.method, exchange, request, uriVariableValues);\n\n\t\t\t// Invoke the method\n\t\t\tthis.method.setAccessible(true);","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/resource/SyncMcpResourceMethodCallback.java#L96-L132","documentation":"SyncMcpResourceMethodCallback.apply requires a non-null ReadResourceRequest because it immediately reads request.uri() to extract URI variables. A null request would cause an NPE deeper in, so the callback fails fast with IllegalArgumentException('Request must not be null').","triggerScenarios":"Calling apply(exchange, null) directly — typically in unit tests, custom dispatchers, or wrapper code around the resource callback.","commonSituations":"Hand-written test harnesses invoking the callback, or custom transport glue that forgets to construct the ReadResourceRequest when forwarding a read-resource call.","solutions":["Construct and pass a ReadResourceRequest with the resource URI before calling apply.","Add a null check at the call site and reject the request upstream with a proper error response.","In tests, use a fixture/builder that always produces a valid ReadResourceRequest."],"exampleFix":"// before\ncallback.apply(exchange, null);\n\n// after\nif (request == null) { return errorResponse(\"read missing request\"); }\ncallback.apply(exchange, new ReadResourceRequest(new McpResourceUri(\"docs://readme\")));","handlingStrategy":"validation","validationCode":"if (request == null) {\n    throw new McpError(\"read resource failed: request must not be null\");\n}","typeGuard":"static boolean validRequest(ReadResourceRequest r) {\n    return r != null && r.uri() != null;\n}","tryCatchPattern":"try {\n    return callback.apply(exchange, request);\n} catch (IllegalArgumentException e) {\n    if (\"Request must not be null\".equals(e.getMessage())) {\n        log.warn(\"Dropped null read-resource request\");\n        return new ReadResourceResult(List.of());\n    } throw e;\n}","preventionTips":["Never call apply() with a literal null request; wrap callback invocation in a null-checking adapter.","Use Objects.requireNonNull(request) early in custom dispatchers to fail at the right layer.","In tests, centralize request construction in a builder/fixture so nulls cannot slip through."],"tags":["mcp","null-argument","request-validation","illegal-argument"],"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"}