{"record":{"id":"702736b1b816a6b1","repo":"spring-projects/spring-ai","slug":"unsupported-exchange-type-exchangetype-for-met","errorCode":null,"errorMessage":"Unsupported exchange type: ${exchangeType} for method: ${method} in ${declaringClass}","messagePattern":"Unsupported exchange type: (.+?) for method: (.+?) in (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java","lineNumber":87,"sourceCode":"\t\t\t\treturn syncServerExchange.transportContext();\n\t\t\t}\n\t\t\telse if (exchange instanceof McpAsyncServerExchange asyncServerExchange) {\n\t\t\t\tthrow new IllegalArgumentException(\"Unsupported Async exchange type: \"\n\t\t\t\t\t\t+ asyncServerExchange.getClass().getName() + \" for Sync method: \" + method.getName() + \" in \"\n\t\t\t\t\t\t+ method.getDeclaringClass().getName());\n\t\t\t}\n\t\t}\n\t\telse if (McpSyncServerExchange.class.isAssignableFrom(paramType)) {\n\t\t\tif (exchange instanceof McpSyncServerExchange syncServerExchange) {\n\t\t\t\treturn syncServerExchange;\n\t\t\t}\n\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Unsupported exchange type: \" + (exchange != null ? exchange.getClass().getName() : \"null\")\n\t\t\t\t\t\t\t+ \" for Sync method: \" + method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t\t}\n\n\t\tthrow new IllegalArgumentException(\n\t\t\t\t\"Unsupported exchange type: \" + (exchange != null ? exchange.getClass().getName() : \"null\")\n\t\t\t\t\t\t+ \" for method: \" + method.getName() + \" in \" + method.getDeclaringClass().getName());\n\t}\n\n\t/**\n\t * Apply the callback to the given exchange and request.\n\t * <p>\n\t * This method builds the arguments for the method call, invokes the method, and\n\t * converts the result to a GetPromptResult.\n\t * @param exchange The server exchange, may be null if the method doesn't require it\n\t * @param request The prompt request, must not be null\n\t * @return The prompt result\n\t * @throws McpError if there is an error invoking the prompt method\n\t * @throws IllegalArgumentException if the request is null\n\t */\n\t@Override\n\tpublic GetPromptResult apply(McpSyncServerExchange exchange, GetPromptRequest request) {\n\t\tif (request == null) {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java#L69-L105","documentation":"The final fallback in SyncMcpPromptMethodCallback.assignExchangeType fires when the method's exchange parameter is neither McpTransportContext nor McpSyncServerExchange and the runtime exchange object matches no supported type (or is null). It throws IllegalArgumentException describing the unrecognized exchange type for the method.","triggerScenarios":"Invoking a sync prompt callback whose parameter is not an exchange/context type, or whose runtime exchange is of an unexpected class or null.","commonSituations":"Hand-written method signatures with unsupported exchange-like parameters; custom transports producing novel exchange objects; internal misuse of the callback API.","solutions":["Declare the exchange parameter as McpSyncServerExchange or McpTransportContext","Pass a supported exchange object when invoking the callback","Align server and callback types so dispatch supplies the expected exchange"],"exampleFix":"// before\npublic GetPromptResult p(Object exchange, Request req) {...}\n// after\npublic GetPromptResult p(McpSyncServerExchange exchange, Request req) {...}","handlingStrategy":"type-guard","validationCode":"boolean validParam(Method m) { Class<?>[] ps = m.getParameterTypes(); return Arrays.stream(ps).allMatch(t -> McpSyncServerExchange.class.isAssignableFrom(t) || McpTransportContext.class.isAssignableFrom(t) || !isExchangeLike(t)); }","typeGuard":"boolean supportedExchange(Object e) { return e instanceof McpSyncServerExchange || e instanceof McpTransportContext; }","tryCatchPattern":"try { r = callback.apply(exchange, req); } catch (IllegalArgumentException e) { log.error(\"Unsupported exchange type for prompt method: {}\", e.getMessage(), e); }","preventionTips":["Declare exchange parameters only as McpSyncServerExchange or McpTransportContext","Avoid loosely typed (Object) exchange parameters","Cover every registered prompt with a dispatch-level test"],"tags":["mcp","exchange-type","prompt-method","internal"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}