spring-projects/spring-ai · error · IllegalArgumentException

Unsupported exchange type: ${exchangeType} for method: ${met

Error message

Unsupported exchange type: ${exchangeType} for method: ${method} in ${declaringClass}

What it means

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.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java:87

				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 "
						+ method.getDeclaringClass().getName());
			}
		}
		else if (McpSyncServerExchange.class.isAssignableFrom(paramType)) {
			if (exchange instanceof McpSyncServerExchange syncServerExchange) {
				return syncServerExchange;
			}

			throw new IllegalArgumentException(
					"Unsupported exchange type: " + (exchange != null ? exchange.getClass().getName() : "null")
							+ " for Sync method: " + method.getName() + " in " + method.getDeclaringClass().getName());
		}

		throw new IllegalArgumentException(
				"Unsupported exchange type: " + (exchange != null ? exchange.getClass().getName() : "null")
						+ " for method: " + method.getName() + " in " + method.getDeclaringClass().getName());
	}

	/**
	 * Apply the callback to the given exchange and request.
	 * <p>
	 * This method builds the arguments for the method call, invokes the method, and
	 * converts the result to a GetPromptResult.
	 * @param exchange The server exchange, may be null if the method doesn't require it
	 * @param request The prompt request, must not be null
	 * @return The prompt result
	 * @throws McpError if there is an error invoking the prompt method
	 * @throws IllegalArgumentException if the request is null
	 */
	@Override
	public GetPromptResult apply(McpSyncServerExchange exchange, GetPromptRequest request) {
		if (request == null) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Declare the exchange parameter as McpSyncServerExchange or McpTransportContext
  2. Pass a supported exchange object when invoking the callback
  3. Align server and callback types so dispatch supplies the expected exchange

Example fix

// before
public GetPromptResult p(Object exchange, Request req) {...}
// after
public GetPromptResult p(McpSyncServerExchange exchange, Request req) {...}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean validParam(Method m) { Class<?>[] ps = m.getParameterTypes(); return Arrays.stream(ps).allMatch(t -> McpSyncServerExchange.class.isAssignableFrom(t) || McpTransportContext.class.isAssignableFrom(t) || !isExchangeLike(t)); }

Type guard

boolean supportedExchange(Object e) { return e instanceof McpSyncServerExchange || e instanceof McpTransportContext; }

Try / catch

try { r = callback.apply(exchange, req); } catch (IllegalArgumentException e) { log.error("Unsupported exchange type for prompt method: {}", e.getMessage(), e); }

Prevention

When it happens

Trigger: Invoking a sync prompt callback whose parameter is not an exchange/context type, or whose runtime exchange is of an unexpected class or null.

Common situations: Hand-written method signatures with unsupported exchange-like parameters; custom transports producing novel exchange objects; internal misuse of the callback API.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/702736b1b816a6b1. Report an issue: GitHub.