spring-projects/spring-ai · error · java.lang.IllegalArgumentException

Unsupported exchange type: {exchange != null ? exchange.getC

Error message

Unsupported exchange type: {exchange != null ? exchange.getClass().getName() : "null"} for method: {method.getName()} in {method.getDeclaringClass().getName()}

What it means

The fallback branch of assignExchangeType in AsyncStatelessMcpPromptMethodCallback throws when the runtime exchange object is neither McpTransportContext, McpSyncServerExchange, nor McpAsyncServerExchange (or is null). It signals the callback was invoked with an unrecognized exchange type from an unsupported transport path.

Source

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

	@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());

			}
			else if (exchange instanceof McpAsyncServerExchange asyncServerExchange) {
				return asyncServerExchange.transportContext();
			}
		}

		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 context and request.
	 * <p>
	 * This method builds the arguments for the method call, invokes the method, and
	 * converts the result to a GetPromptResult.
	 * @param context The transport context, may be null if the method doesn't require it
	 * @param request The prompt request, must not be null
	 * @return A Mono that emits the prompt result
	 * @throws McpError if there is an error invoking the prompt method
	 * @throws IllegalArgumentException if the request is null
	 */
	@Override
	public Mono<GetPromptResult> apply(McpTransportContext context, GetPromptRequest request) {
		if (request == null) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Pass a supported exchange type: McpTransportContext, McpSyncServerExchange, or McpAsyncServerExchange
  2. If the exchange is null, ensure the server supplies a real exchange/transport context
  3. Upgrade or align library versions so transport and callback layers agree on exchange types

Example fix

// before
callback.apply(new MyCustomExchange(), request);
// after
callback.apply(mcpAsyncServerExchange, request);
Defensive patterns

Strategy: type-guard

Validate before calling

if (exchange == null || !(exchange instanceof McpTransportContext || exchange instanceof McpSyncServerExchange || exchange instanceof McpAsyncServerExchange)) throw new IllegalArgumentException("unsupported exchange");

Type guard

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

Try / catch

try { ctx = callback.apply(exchange, req); } catch (IllegalArgumentException e) { log.error("Unsupported exchange {}", exchange == null ? "null" : exchange.getClass(), e); }

Prevention

When it happens

Trigger: Invoking the prompt callback with an exchange argument of an unexpected type (or null) that no branch of assignExchangeType can handle.

Common situations: Custom transport implementations passing a novel exchange object; misuse of the callback API by calling apply/assignExchangeType directly with the wrong argument; version mismatches where new exchange types are not yet handled.

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/e56c54fa13d7c2e4. Report an issue: GitHub.