spring-projects/spring-ai · error · IllegalArgumentException

Updated resources list must not be null

Error message

Updated resources list must not be null

What it means

SyncMcpResourceListChangedMethodCallback.accept(List<McpSchema.Resource>) rejects a null updatedResources list with IllegalArgumentException before invoking the consumer method. The library treats null as an invalid notification payload rather than an empty change set.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/resource/SyncMcpResourceListChangedMethodCallback.java:56

		implements Consumer<List<McpSchema.Resource>> {

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

	/**
	 * Accept the resource list change notification and process it.
	 * <p>
	 * This method builds the arguments for the method call and invokes the method.
	 * @param updatedResources The updated list of resources, must not be null
	 * @throws McpResourceListChangedConsumerMethodException if there is an error invoking
	 * the resource list changed consumer method
	 * @throws IllegalArgumentException if the updatedResources is null
	 */
	@Override
	public void accept(List<McpSchema.Resource> updatedResources) {
		if (updatedResources == null) {
			throw new IllegalArgumentException("Updated resources list must not be null");
		}

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

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

	/**
	 * Validates that the method return type is compatible with the resource list changed

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Pass an empty List (List.of() / Collections.emptyList()) instead of null when no resources exist.
  2. Null-check the notification payload before invoking accept().
  3. If this comes from a custom transport, normalize null lists to empty lists at the transport layer.

Example fix

// before
callback.accept(null);
// after
callback.accept(updatedResources == null ? List.of() : updatedResources);
Defensive patterns

Strategy: validation

Validate before calling

if (updatedResources == null) { updatedResources = List.of(); }

Type guard

static List<McpSchema.Resource> orEmpty(List<McpSchema.Resource> l) {
    return l == null ? List.of() : l;
}

Try / catch

try {
    callback.accept(updatedResources);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Updated resources list must not be null")) {
        log.warn("Received null resources payload; treating as empty");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling accept(null) directly, or a server/notification path delivering a resource-list-changed event with a null resources list into a sync callback.

Common situations: Custom or test harness code simulating resource change notifications and passing null instead of an empty list.

Related errors


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