spring-projects/spring-ai · error · java.lang.IllegalArgumentException
Stateless Streamable-Http prompt method must not declare par
Error message
Stateless Streamable-Http prompt method must not declare parameter of type: {paramType.getName()}. Use McpTransportContext instead. Method: {this.method.getName()} in {this.method.getDeclaringClass().getName()} What it means
In stateless Streamable-HTTP mode there is no per-session server exchange, so an async stateless prompt method must not take McpSyncServerExchange or McpAsyncServerExchange parameters. The callback rejects such parameters at validation time and directs you to use the session-less McpTransportContext instead.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AsyncStatelessMcpPromptMethodCallback.java:59
* callback functions that can be used to handle prompt requests asynchronously in
* stateless environments. It supports various method signatures and return types.
*
* @author Christian Tzolov
*/
public final class AsyncStatelessMcpPromptMethodCallback extends AbstractMcpPromptMethodCallback
implements BiFunction<McpTransportContext, GetPromptRequest, Mono<GetPromptResult>> {
private AsyncStatelessMcpPromptMethodCallback(Builder builder) {
super(builder.method, builder.bean, builder.prompt);
}
@Override
protected void validateParamType(Class<?> paramType) {
if (McpSyncServerExchange.class.isAssignableFrom(paramType)
|| McpAsyncServerExchange.class.isAssignableFrom(paramType)) {
throw new IllegalArgumentException(
"Stateless Streamable-Http prompt method must not declare parameter of type: " + paramType.getName()
+ ". Use McpTransportContext instead." + " Method: " + this.method.getName() + " in "
+ this.method.getDeclaringClass().getName());
}
}
@Override
protected Object assignExchangeType(Class<?> paramType, Object exchange) {
if (McpTransportContext.class.isAssignableFrom(paramType)) {
if (exchange instanceof McpTransportContext transportContext) {
return transportContext;
}
else if (exchange instanceof McpSyncServerExchange syncServerExchange) {
throw new IllegalArgumentException("Unsupported Sync exchange type: "
+ syncServerExchange.getClass().getName() + " for Sync method: " + method.getName() + " in "
+ method.getDeclaringClass().getName());
View on GitHub (pinned to 98a7beda4f)
Solutions
- Replace the McpSyncServerExchange/McpAsyncServerExchange parameter with McpTransportContext
- Remove the exchange parameter entirely if no transport context is needed
- Keep the stateful server mode if the method genuinely needs the exchange
Example fix
// before
public Mono<GetPromptResult> prompt(McpAsyncServerExchange exchange, Request req) {...}
// after
public Mono<GetPromptResult> prompt(McpTransportContext context, Request req) {...} Defensive patterns
Strategy: validation
Validate before calling
boolean statelessSafe(Method m) { return Arrays.stream(m.getParameterTypes()).noneMatch(t -> McpSyncServerExchange.class.isAssignableFrom(t) || McpAsyncServerExchange.class.isAssignableFrom(t)); } Try / catch
try { registerPrompts(bean); } catch (IllegalArgumentException e) { log.error("Stateless method misconfigured: {}", e.getMessage()); } Prevention
- Prefer McpTransportContext parameters in stateless deployments
- Audit @McpPrompt signatures when switching stateful to stateless mode
- Document that stateless mode forbids exchange parameters
When it happens
Trigger: Declaring an @McpPrompt method with a McpSyncServerExchange or McpAsyncServerExchange parameter while the server runs in stateless Streamable-Http mode and is wired via AsyncStatelessMcpPromptMethodCallback.
Common situations: Switching a stateful MCP server to stateless Streamable-Http without updating method signatures; copying stateful examples into a stateless configuration.
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
- Sync prompt method must not declare parameter of type: {para
- Stateless Streamable-Http prompt method must not declare par
- Stateless Streamable-Http prompt method must not declare par
- Parameter must be of type List<McpSchema.Resource>:
- Method parameters must be exchange, CompleteRequest, Complet
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/79165296b2502d9f.
Report an issue: GitHub.