spring-projects/spring-ai · error · McpResourceListChangedConsumerMethodException

Error invoking resource list changed consumer method: " +…

Error message

Error invoking resource list changed consumer method: " + this.method.getName()

What it means

When reflective invocation of the sync resource-list-changed consumer method fails (IllegalAccessException, InvocationTargetException wrapping any user-code exception, etc.), the library wraps the cause in McpResourceListChangedConsumerMethodException with this message. The real cause is the attached 'e' exception.

Solutions

  1. Inspect getCause() of McpResourceListChangedConsumerMethodException for the actual failure and fix that code.
  2. Open the callback method's package to spring-ai (add opens/exports in module-info or --add-opens) if setAccessible fails.
  3. Add try/catch or defensive checks inside the consumer method so it does not propagate runtime exceptions.

Example fix

// before
public void onResourcesChanged(List<McpSchema.Resource> r) { parse(r.get(0)); }
// after
public void onResourcesChanged(List<McpSchema.Resource> r) { if (r != null && !r.isEmpty()) parse(r.get(0)); }
Defensive patterns

Strategy: try-catch

Validate before calling

Method m = bean.getClass().getMethod("onResourcesChanged", List.class);
m.setAccessible(true); // fail fast if JPMS blocks access
Objects.requireNonNull(bean);

Try / catch

try {
    callback.accept(resources);
} catch (McpResourceListChangedConsumerMethodException e) {
    log.error("Resource-list-changed handler '{}' failed", e.getMessage(), e.getCause());
}

Prevention

When it happens

Trigger: The registered consumer method throws any exception at invocation, is inaccessible (setAccessible denied by security/JPMS), or its declaring bean is in a bad state (e.g. closed client).

Common situations: User code inside the callback throws (NPE, downstream call failure); Java module system blocks setAccessible on the method's package.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

	 * 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
	 * consumer callback.
	 * @param method The method to validate
	 * @throws IllegalArgumentException if the return type is not compatible
	 */
	@Override
	protected void validateReturnType(Method method) {
		Class<?> returnType = method.getReturnType();

		if (returnType != void.class) {
			throw new IllegalArgumentException("Method must have void return type: " + method.getName() + " in "
					+ method.getDeclaringClass().getName() + " returns " + returnType.getName());
		}

View on GitHub (pinned to 98a7beda4f)