{"record":{"id":"6efde408e3f2baef","repo":"spring-projects/spring-ai","slug":"method-must-return-either-getpromptresult-list-pr-6efde4","errorCode":null,"errorMessage":"Method must return either GetPromptResult, List<PromptMessage>, List<String>, PromptMessage, or String: ${method} in ${declaringClass} returns ${returnType}","messagePattern":"Method must return either GetPromptResult, List<PromptMessage>, List<String>, PromptMessage, or String: (.+?) in (.+?) returns (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncStatelessMcpPromptMethodCallback.java","lineNumber":144,"sourceCode":"\t\t\t\t.build();\n\t\t}\n\t}\n\n\t@Override\n\tprotected boolean isSupportedExchangeOrContextType(Class<?> paramType) {\n\t\treturn McpTransportContext.class.isAssignableFrom(paramType);\n\t}\n\n\t@Override\n\tprotected void validateReturnType(Method method) {\n\t\tClass<?> returnType = method.getReturnType();\n\n\t\tboolean validReturnType = GetPromptResult.class.isAssignableFrom(returnType)\n\t\t\t\t|| List.class.isAssignableFrom(returnType) || PromptMessage.class.isAssignableFrom(returnType)\n\t\t\t\t|| String.class.isAssignableFrom(returnType);\n\n\t\tif (!validReturnType) {\n\t\t\tthrow new IllegalArgumentException(\"Method must return either GetPromptResult, List<PromptMessage>, \"\n\t\t\t\t\t+ \"List<String>, PromptMessage, or String: \" + method.getName() + \" in \"\n\t\t\t\t\t+ method.getDeclaringClass().getName() + \" returns \" + returnType.getName());\n\t\t}\n\t}\n\n\t/**\n\t * Create a new builder.\n\t * @return A new builder instance\n\t */\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\t/**\n\t * Builder for creating SyncStatelessMcpPromptMethodCallback instances.\n\t * <p>\n\t * This builder provides a fluent API for constructing\n\t * SyncStatelessMcpPromptMethodCallback instances with the required parameters.","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncStatelessMcpPromptMethodCallback.java#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@McpPrompt(description = \"summary\")\npublic SummaryReport summarize(String topic) {\n    return new SummaryReport(topic);\n}\n\n// after\n@McpPrompt(description = \"summary\")\npublic PromptMessage summarize(String topic) {\n    return new PromptMessage(Role.ASSISTANT, new TextContent(\"Summary of \" + topic));\n}","handlingStrategy":"validation","validationCode":"static boolean hasValidStatelessPromptReturnType(Method m) {\n    Class<?> r = m.getReturnType();\n    return GetPromptResult.class.isAssignableFrom(r) || List.class.isAssignableFrom(r)\n        || PromptMessage.class.isAssignableFrom(r) || String.class.isAssignableFrom(r);\n}","typeGuard":null,"tryCatchPattern":"try {\n    statelessServer.addPrompt(spec);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"@McpPrompt return type not supported in stateless server\", e);\n}","preventionTips":["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."],"tags":["mcp","java","invalid-return-type","stateless","annotation-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}