{"record":{"id":"dc4e84b7fe7d2aae","repo":"spring-projects/spring-ai","slug":"notification-must-not-be-null-dc4e84","errorCode":null,"errorMessage":"Notification must not be null","messagePattern":"Notification must not be null","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/progress/SyncMcpProgressMethodCallback.java","lineNumber":60,"sourceCode":"\t\tif (!void.class.equals(method.getReturnType())) {\n\t\t\tthrow new IllegalArgumentException(\"Synchronous progress methods must return void: \" + method.getName()\n\t\t\t\t\t+ \" in \" + method.getDeclaringClass().getName() + \" returns \" + method.getReturnType().getName());\n\t\t}\n\t}\n\n\t/**\n\t * Accept the progress notification and process it.\n\t * <p>\n\t * This method builds the arguments for the method call and invokes the method.\n\t * @param notification The progress notification, must not be null\n\t * @throws McpProgressMethodException if there is an error invoking the progress\n\t * method\n\t * @throws IllegalArgumentException if the notification is null\n\t */\n\t@Override\n\tpublic void accept(ProgressNotification notification) {\n\t\tif (notification == null) {\n\t\t\tthrow new IllegalArgumentException(\"Notification 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, null, notification);\n\n\t\t\t// Invoke the method\n\t\t\tthis.method.setAccessible(true);\n\t\t\tthis.method.invoke(this.bean, args);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new McpProgressMethodException(\"Error invoking progress method: \" + this.method.getName(), e);\n\t\t}\n\t}\n\n\t/**\n\t * Create a new builder.\n\t * @return A new builder instance","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/progress/SyncMcpProgressMethodCallback.java#L42-L78","documentation":"SyncMcpProgressMethodCallback.accept() is the Consumer invoked when a progress notification arrives for a method annotated with @McpProgress. It performs a fail-fast null check on the ProgressNotification before reflectively invoking the annotated method, because a null notification cannot be meaningfully mapped to callback arguments.","triggerScenarios":"Calling accept(null) directly on a SyncMcpProgressMethodCallback, or registering a progress handler pipeline that delivers a null ProgressNotification to the consumer (e.g. a custom ProgressNotification handler that forwards null).","commonSituations":"Custom transport or session wrappers that invoke progress consumers without checking for a null notification; unit tests passing null to verify callback behavior; hand-built callback registrations bypassing the framework's normal dispatch which always supplies a real notification.","solutions":["Ensure the code calling accept() never passes null; check the notification for null before invoking the consumer.","If you own the dispatching code, skip processing silently (or log) when no ProgressNotification is available instead of forwarding null.","Catch IllegalArgumentException around accept() if null deliveries are possible in your pipeline and treat them as no-ops."],"exampleFix":"// before\nconsumer.accept(notification);\n// after\nif (notification != null) {\n    consumer.accept(notification);\n}","handlingStrategy":"validation","validationCode":"if (notification == null) { return; // or log and skip }\nconsumer.accept(notification);","typeGuard":"boolean hasNotification(ProgressNotification n) { return n != null; }","tryCatchPattern":"try { consumer.accept(notification); } catch (IllegalArgumentException e) { log.warn(\"Null progress notification rejected: {}\", e.getMessage()); }","preventionTips":["Never forward raw notifications from transports without a null check","Wrap progress consumers in a null-safe adapter","In tests, always pass a constructed ProgressNotification rather than null"],"tags":["java","mcp","null-check","progress-notification"],"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"}