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

Unsupported result type: {result != null ? result.getClass()

Error message

Unsupported result type: {result != null ? result.getClass().getName() : "null"}

What it means

After invoking the prompt method, convertToGetPromptResult converts the returned object into a GetPromptResult. Supported return shapes are GetPromptResult, List<PromptMessage>, List<String>, PromptMessage, and String. Anything else (including null, whose class name prints as "null") cannot be converted, so this IllegalArgumentException is thrown at invocation time.

Source

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

							.build())
						.toList();
					return GetPromptResult.builder(messages).build();
				}
			}
		}
		else if (result instanceof PromptMessage) {
			// If the result is a single PromptMessage, wrap it in a list
			return GetPromptResult.builder(List.of((PromptMessage) result)).build();
		}
		else if (result instanceof String) {
			// If the result is a simple string, create a single assistant message with
			// that content
			return GetPromptResult.builder(List.of(PromptMessage
				.builder(McpSchema.Role.ASSISTANT, McpSchema.TextContent.builder((String) result).build())
				.build())).build();
		}

		throw new IllegalArgumentException(
				"Unsupported result type: " + (result != null ? result.getClass().getName() : "null"));
	}

	/**
	 * Abstract builder for creating prompt method callback instances.
	 *
	 * @param <B> The builder type
	 * @param <T> The callback type
	 */
	protected abstract static class AbstractBuilder<B extends AbstractBuilder<B, T>, T extends AbstractMcpPromptMethodCallback> {

		protected Method method;

		protected Object bean;

		protected Prompt prompt;

		/**

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Change the method to return one of the supported types: String, PromptMessage, List<String>, List<PromptMessage>, or GetPromptResult.
  2. Convert your domain object to a String/PromptMessage inside the method before returning.
  3. Return GetPromptResult.builder(...).build() directly for full control over roles and content.
  4. Ensure the method never returns null; return an empty String or an empty-message GetPromptResult instead.

Example fix

// before
@McpPrompt(name = "summary")
public Summary summarize(String text) { return new Summary(text); }
// after
@McpPrompt(name = "summary")
public GetPromptResult summarize(String text) {
    return GetPromptResult.builder(List.of(PromptMessage.builder(McpSchema.Role.ASSISTANT,
        McpSchema.TextContent.builder(buildSummary(text)).build()).build())).build();
}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean hasSupportedPromptReturnType(Method m) {
    Class<?> r = m.getReturnType();
    return GetPromptResult.class.isAssignableFrom(r) || String.class.isAssignableFrom(r)
        || PromptMessage.class.isAssignableFrom(r) || List.class.isAssignableFrom(r);
}

Type guard

Object ensurePromptResult(Object result) {
    if (result == null) return GetPromptResult.builder(List.of()).build();
    if (result instanceof GetPromptResult || result instanceof String
        || result instanceof PromptMessage || result instanceof List) return result;
    throw new IllegalStateException("Unsupported prompt return type: " + result.getClass());
}

Try / catch

try {
    GetPromptResult r = callback.apply(exchange, request);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unsupported result type")) {
        log.error("Fix the @McpPrompt method return type", e);
        return GetPromptResult.builder(List.of()).build();
    }
    throw e;
}

Prevention

When it happens

Trigger: An @McpPrompt method returns an unsupported type such as a POJO, Optional<String>, Map, Message object, or null; the callback then hits the final throw in convertToGetPromptResult.

Common situations: Returning a domain object assuming auto-serialization; returning Optional.of(text); methods refactored to return custom result wrappers; forgetting that null returns are rejected.

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