spring-projects/spring-ai · error · IllegalArgumentException
Method must return either GetPromptResult, List<PromptMessag
Error message
Method must return either GetPromptResult, List<PromptMessage>, List<String>, PromptMessage, or String: ${method} in ${declaringClass} returns ${returnType} What it means
Identical to the stateful sync prompt check (error 190) but in SyncStatelessMcpPromptMethodCallback: a @McpPrompt method in a stateless Streamable-Http server must return GetPromptResult, List, PromptMessage, or String. validateReturnType throws IllegalArgumentException for any other return type, failing at startup.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncStatelessMcpPromptMethodCallback.java:144
.build();
}
}
@Override
protected boolean isSupportedExchangeOrContextType(Class<?> paramType) {
return McpTransportContext.class.isAssignableFrom(paramType);
}
@Override
protected void validateReturnType(Method method) {
Class<?> returnType = method.getReturnType();
boolean validReturnType = GetPromptResult.class.isAssignableFrom(returnType)
|| List.class.isAssignableFrom(returnType) || PromptMessage.class.isAssignableFrom(returnType)
|| String.class.isAssignableFrom(returnType);
if (!validReturnType) {
throw new IllegalArgumentException("Method must return either GetPromptResult, List<PromptMessage>, "
+ "List<String>, PromptMessage, or String: " + method.getName() + " in "
+ method.getDeclaringClass().getName() + " returns " + returnType.getName());
}
}
/**
* Create a new builder.
* @return A new builder instance
*/
public static Builder builder() {
return new Builder();
}
/**
* Builder for creating SyncStatelessMcpPromptMethodCallback instances.
* <p>
* This builder provides a fluent API for constructing
* SyncStatelessMcpPromptMethodCallback instances with the required parameters.View on GitHub (pinned to 98a7beda4f)
Solutions
- Change the return type to GetPromptResult, List<PromptMessage>, List<String>, PromptMessage, or String.
- Convert custom DTOs into PromptMessage instances with appropriate Content.
- Return a simple String for plain-text prompts.
Example fix
// before
@McpPrompt(description = "summary")
public SummaryReport summarize(String topic) {
return new SummaryReport(topic);
}
// after
@McpPrompt(description = "summary")
public PromptMessage summarize(String topic) {
return new PromptMessage(Role.ASSISTANT, new TextContent("Summary of " + topic));
} Defensive patterns
Strategy: validation
Validate before calling
static boolean hasValidStatelessPromptReturnType(Method m) {
Class<?> r = m.getReturnType();
return GetPromptResult.class.isAssignableFrom(r) || List.class.isAssignableFrom(r)
|| PromptMessage.class.isAssignableFrom(r) || String.class.isAssignableFrom(r);
} Try / catch
try {
statelessServer.addPrompt(spec);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("@McpPrompt return type not supported in stateless server", e);
} Prevention
- Keep prompt return types within the whitelist regardless of server mode.
- Run annotation-signature tests in CI covering both stateful and stateless registrations.
- Return PromptMessage or String for simple prompts instead of custom DTOs.
When it happens
Trigger: Annotating a prompt method in a stateless server whose return type is a POJO, Optional, primitive, Map, or other non-whitelisted type; the same whitelist check as the stateful variant is applied at registration.
Common situations: Reusing tool methods as prompts (tools allow broader returns); returning builder-style custom result objects; migrating methods between sync/async callbacks where return-type rules differ.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Method must return either GetPromptResult, List<PromptMessag
- Stateless Streamable-Http prompt method must not declare par
- Stateless Streamable-Http prompt method must not declare par
- Unsupported Sync exchange type: ${exchangeType} for Sync met
- Unsupported exchange type: ${exchangeType} for method: ${met
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/6efde408e3f2baef.
Report an issue: GitHub.