spring-projects/spring-ai · error · IllegalArgumentException

Notification must not be null

Error message

Notification must not be null

What it means

SyncMcpLoggingMethodCallback.accept() requires a non-null LoggingMessageNotification before dispatching to the annotated consumer method. Passing null throws IllegalArgumentException immediately. The framework itself always passes a real notification, so this usually indicates direct programmatic use of the callback with a null argument.

Solutions

  1. Construct a valid LoggingMessageNotification before calling accept().
  2. Guard the call site: only invoke accept() when the notification is non-null.
  3. In custom transports, drop or log null notifications instead of forwarding them.
  4. In tests, use a builder/factory for a sample notification rather than passing null.

Example fix

// before
loggingCallback.accept(notification); // notification may be null
// after
if (notification != null) {
    loggingCallback.accept(notification);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (notification == null) { logger.warn("skipping null logging notification"); return; }

Type guard

static boolean isUsable(LoggingMessageNotification n) {
    return n != null;
}

Try / catch

try {
    callback.accept(notification);
} catch (IllegalArgumentException e) {
    logger.warn("Rejected notification: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Invoking callback.accept(null) directly in a unit test or custom transport wiring; a custom notification source that forwards null notifications into the consumer; calling the consumer Function-style with an unset variable.

Common situations: Unit tests exercising the callback without building a LoggingMessageNotification; custom MCP transport implementations that don't filter null upstream events; Optional misuse where Optional.empty() was unwrapped to null via .get()-style patterns.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/f4d1eee9acd4afef. Report an issue: GitHub.

Appendix: source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/logging/SyncMcpLoggingMethodCallback.java:55

		implements Consumer<LoggingMessageNotification> {

	private SyncMcpLoggingMethodCallback(Builder builder) {
		super(builder.method, builder.bean);
	}

	/**
	 * Accept the logging message notification and process it.
	 * <p>
	 * This method builds the arguments for the method call and invokes the method.
	 * @param notification The logging message notification, must not be null
	 * @throws McpLoggingConsumerMethodException if there is an error invoking the logging
	 * consumer method
	 * @throws IllegalArgumentException if the notification is null
	 */
	@Override
	public void accept(LoggingMessageNotification notification) {
		if (notification == null) {
			throw new IllegalArgumentException("Notification must not be null");
		}

		try {
			// Build arguments for the method call
			Object[] args = this.buildArgs(this.method, null, notification);

			// Invoke the method
			this.method.setAccessible(true);
			this.method.invoke(this.bean, args);
		}
		catch (Exception e) {
			throw new McpLoggingConsumerMethodException(
					"Error invoking logging consumer method: " + this.method.getName(), e);
		}
	}

	/**
	 * Validates that the method return type is compatible with the logging consumer

View on GitHub (pinned to 98a7beda4f)