spring-projects/spring-ai · error · McpSamplingMethodException
Error invoking sampling method
Error message
Error invoking sampling method: {methodName} What it means
SyncMcpSamplingMethodCallback.apply() wraps any Exception thrown while reflectively invoking the sampling method into McpSamplingMethodException with message 'Error invoking sampling method: <methodName>'. This signals that the user's sampling handler method itself failed — the message carries the method name and the cause carries the original exception.
Solutions
- Read getCause() on the McpSamplingMethodException to find the real failure
- Fix the bug inside the sampling handler method named in the message
- Add try/catch or validation inside the handler and return an error CreateMessageResult instead of throwing
- Log the full stack trace with the cause chain before rethrowing
Example fix
// before
CreateMessageResult sample(CreateMessageRequest req) {
return callModel(req); // throws IOException
}
// after
CreateMessageResult sample(CreateMessageRequest req) {
try {
return callModel(req);
} catch (IOException e) {
throw new UncheckedIOException(e); // surfaces as cause
}
} Defensive patterns
Strategy: try-catch
Try / catch
try {
result = callback.apply(request);
} catch (McpSamplingMethodException e) {
log.error("Sampling handler {} failed", e.getMessage(), e.getCause());
return fallbackCreateMessageResult(request);
} Prevention
- Keep handler methods small and validate inputs before heavy work
- Catch and translate IO/checked exceptions inside the handler
- Log the cause chain, not just the wrapper message
When it happens
Trigger: The registered sampling method throws any Exception during method.invoke — e.g. NPE inside the handler, IO failure assembling the message, or a checked exception raised in the handler body.
Common situations: Handler logic bugs (null fields on the request), downstream API calls inside the handler failing, handler code throwing custom checked exceptions.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- Currently only methods with a single CreateMessageRequest…
- Currently only methods with a single CreateMessageRequest…
- Method must have at least 1 parameter (CreateMessageRequest)
- Bean must not be null
- ClassNotFoundException (wrapped RuntimeException)
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/18d299532769ba41.
Report an issue: GitHub.
Appendix: source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/sampling/SyncMcpSamplingMethodCallback.java:72
@Override
public CreateMessageResult apply(CreateMessageRequest request) {
if (request == null) {
throw new IllegalArgumentException("Request must not be null");
}
try {
// Build arguments for the method call
Object[] args = this.buildArgs(this.method, null, request);
// Invoke the method
this.method.setAccessible(true);
Object result = this.method.invoke(this.bean, args);
// Return the result
return (CreateMessageResult) result;
}
catch (Exception e) {
throw new McpSamplingMethodException("Error invoking sampling method: " + this.method.getName(), e);
}
}
/**
* Validates that the method return type is compatible with the sampling 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 (!CreateMessageResult.class.isAssignableFrom(returnType)) {
throw new IllegalArgumentException("Method must return CreateMessageResult: " + method.getName() + " in "
+ method.getDeclaringClass().getName() + " returns " + returnType.getName());
}
}
View on GitHub (pinned to 98a7beda4f)