spring-projects/spring-ai · error · java.lang.IllegalArgumentException
Sync prompt method must not declare parameter of type: {para
Error message
Sync prompt method must not declare parameter of type: {paramType.getName()}. Use McpSyncServerExchange instead. Method: {this.method.getName()} in {this.method.getDeclaringClass().getName()} What it means
Sync prompt methods may receive an McpSyncServerExchange but not an McpAsyncServerExchange, since a synchronous server cannot provide the async exchange. SyncMcpPromptMethodCallback validates each parameter type at registration and throws IllegalArgumentException if it finds the async exchange type.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java:55
*
* This class provides a way to convert methods annotated with {@link McpPrompt} into
* callback functions that can be used to handle prompt requests. It supports various
* method signatures and return types.
*
* @author Christian Tzolov
*/
public final class SyncMcpPromptMethodCallback extends AbstractMcpPromptMethodCallback
implements BiFunction<McpSyncServerExchange, GetPromptRequest, GetPromptResult> {
private SyncMcpPromptMethodCallback(Builder builder) {
super(builder.method, builder.bean, builder.prompt);
}
@Override
protected void validateParamType(Class<?> paramType) {
if (McpAsyncServerExchange.class.isAssignableFrom(paramType)) {
throw new IllegalArgumentException("Sync prompt method must not declare parameter of type: "
+ paramType.getName() + ". Use McpSyncServerExchange 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) {
return syncServerExchange.transportContext();
}
else if (exchange instanceof McpAsyncServerExchange asyncServerExchange) {
throw new IllegalArgumentException("Unsupported Async exchange type: "
+ asyncServerExchange.getClass().getName() + " for Sync method: " + method.getName() + " in "View on GitHub (pinned to 98a7beda4f)
Solutions
- Change the parameter type to McpSyncServerExchange
- Remove the exchange parameter if not needed
- Register the bean with the async server (AsyncMcpPromptMethodCallback) if the method must stay async
Example fix
// before
public GetPromptResult p(McpAsyncServerExchange exchange, Request req) {...}
// after
public GetPromptResult p(McpSyncServerExchange exchange, Request req) {...} Defensive patterns
Strategy: validation
Validate before calling
boolean syncSafe(Method m) { return Arrays.stream(m.getParameterTypes()).noneMatch(t -> McpAsyncServerExchange.class.isAssignableFrom(t)); } Try / catch
try { syncServer.addPrompt(cb); } catch (IllegalArgumentException e) { log.error("Sync method misconfigured: {}", e.getMessage()); } Prevention
- Use McpSyncServerExchange in sync prompt methods
- Keep async signatures out of sync server configurations
- Add a unit test scanning @McpPrompt parameter types per server mode
When it happens
Trigger: Declaring an @McpPrompt method with an McpAsyncServerExchange parameter while registering it with SyncMcpPromptMethodCallback (sync MCP server).
Common situations: Copy-pasting a method signature from async MCP examples into a sync server setup; converting an app from async to sync without changing signatures.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Stateless Streamable-Http prompt method must not declare par
- Unsupported Sync exchange type: {syncServerExchange.getClass
- Unsupported Async exchange type: {asyncServerExchange.getCla
- 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/853b9fa226c06ba6.
Report an issue: GitHub.