spring-projects/spring-ai · error · java.lang.IllegalArgumentException

Notification must not be null

Error message

Notification must not be null

What it means

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.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/progress/SyncMcpProgressMethodCallback.java:60

		if (!void.class.equals(method.getReturnType())) {
			throw new IllegalArgumentException("Synchronous progress methods must return void: " + method.getName()
					+ " in " + method.getDeclaringClass().getName() + " returns " + method.getReturnType().getName());
		}
	}

	/**
	 * Accept the progress notification and process it.
	 * <p>
	 * This method builds the arguments for the method call and invokes the method.
	 * @param notification The progress notification, must not be null
	 * @throws McpProgressMethodException if there is an error invoking the progress
	 * method
	 * @throws IllegalArgumentException if the notification is null
	 */
	@Override
	public void accept(ProgressNotification 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 McpProgressMethodException("Error invoking progress method: " + this.method.getName(), e);
		}
	}

	/**
	 * Create a new builder.
	 * @return A new builder instance

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Ensure the code calling accept() never passes null; check the notification for null before invoking the consumer.
  2. If you own the dispatching code, skip processing silently (or log) when no ProgressNotification is available instead of forwarding null.
  3. Catch IllegalArgumentException around accept() if null deliveries are possible in your pipeline and treat them as no-ops.

Example fix

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

Strategy: validation

Validate before calling

if (notification == null) { return; // or log and skip }
consumer.accept(notification);

Type guard

boolean hasNotification(ProgressNotification n) { return n != null; }

Try / catch

try { consumer.accept(notification); } catch (IllegalArgumentException e) { log.warn("Null progress notification rejected: {}", e.getMessage()); }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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