spring-projects/spring-ai · error · McpPromptListChangedConsumerMethodException
Error invoking prompt list changed consumer method:
Error message
Error invoking prompt list changed consumer method:
What it means
A McpPromptListChangedConsumerMethodException wrapping the underlying failure, thrown by SyncMcpPromptListChangedMethodCallback.accept() when the reflective this.method.invoke(bean, args) call fails. Any exception raised inside the user's handler method (or by argument building/IllegalAccess) is wrapped, with the handler method name in the message and the original cause attached.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/prompt/SyncMcpPromptListChangedMethodCallback.java:68
* the prompt list changed consumer method
* @throws IllegalArgumentException if the updatedPrompts is null
*/
@Override
public void accept(List<McpSchema.Prompt> updatedPrompts) {
if (updatedPrompts == null) {
throw new IllegalArgumentException("Updated prompts list must not be null");
}
try {
// Build arguments for the method call
Object[] args = this.buildArgs(this.method, null, updatedPrompts);
// Invoke the method
this.method.setAccessible(true);
this.method.invoke(this.bean, args);
}
catch (Exception e) {
throw new McpPromptListChangedConsumerMethodException(
"Error invoking prompt list changed consumer method: " + this.method.getName(), e);
}
}
/**
* Validates that the method return type is compatible with the prompt 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)
Solutions
- Inspect getCause() of the McpPromptListChangedConsumerMethodException — the real fix belongs to the wrapped exception.
- Match the handler signature exactly to the expected consumer shape, e.g. void handler(List<McpSchema.Prompt> prompts).
- Fix the bug in the handler body (null checks, downstream calls) that caused the wrapped exception.
- For JPMS access errors, open the package (–add-opens) or keep handler methods in an exported/open package.
Example fix
// before (signature mismatch -> reflective invoke fails)
public void onPromptsChanged(PromptListChangedNotification n) { ... }
// after
public void onPromptsChanged(List<McpSchema.Prompt> updatedPrompts) { ... } Defensive patterns
Strategy: try-catch
Validate before calling
Method m = bean.getClass().getMethod("onPromptsChanged", List.class);
// parameter type check before wiring
if (!List.class.isAssignableFrom(m.getParameterTypes()[0])) {
throw new IllegalStateException("handler must accept List<McpSchema.Prompt>");
} Try / catch
try {
callback.accept(updatedPrompts);
} catch (McpPromptListChangedConsumerMethodException e) {
Throwable cause = e.getCause();
log.error("Prompt list changed handler {} failed: {}", e.getMessage(), cause, cause);
// handle or rethrow based on cause type
} Prevention
- Always inspect getCause() — the wrapped exception carries the real problem.
- Match handler parameter types exactly to List<McpSchema.Prompt>.
- Keep handlers in open/exported packages for reflective access under JPMS.
- Wrap risky handler logic in its own try-catch to avoid propagating failures.
When it happens
Trigger: The handler method throws at runtime (NPE, repository failure, etc.); the method's parameter types do not match the built arguments (IllegalArgumentException from reflection); the method is not accessible and setAccessible fails under a SecurityManager/JPMS strong encapsulation.
Common situations: Handler signature drift — declaring the consumer with wrong parameter types after an MCP SDK upgrade; handler code throwing due to downstream service failures; Java 16+ module encapsulation blocking setAccessible on non-exported classes.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Updated prompts list must not be null
- Error invoking resource list changed consumer method: " + th
- Error invoking complete method:
- Error invoking logging consumer method:
- Error invoking progress method: {this.method.getName()}
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/9011043dad7f084f.
Report an issue: GitHub.