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
- Change the method to return one of the supported types: String, PromptMessage, List<String>, List<PromptMessage>, or GetPromptResult.
- Convert your domain object to a String/PromptMessage inside the method before returning.
- Return GetPromptResult.builder(...).build() directly for full control over roles and content.
- 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
- Restrict @McpPrompt return types to String, PromptMessage, List<String>, List<PromptMessage>, or GetPromptResult.
- Never return null from a prompt method.
- Cover each prompt method with an invocation test that exercises convertToGetPromptResult.
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
- Unsupported return type: {resultClassName}
- Expected Mono<Void> but got Mono<
- Method must have void or Mono<Void> return type:
- Method must have void return type:
- Method must have void or Mono<Void> return type:
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/131986f302884220.
Report an issue: GitHub.