{"record":{"id":"131986f302884220","repo":"spring-projects/spring-ai","slug":"unsupported-result-type-result-null-result","errorCode":null,"errorMessage":"Unsupported result type: {result != null ? result.getClass().getName() : \"null\"}","messagePattern":"Unsupported result type: (.+?)","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AbstractMcpPromptMethodCallback.java","lineNumber":408,"sourceCode":"\t\t\t\t\t\t\t.build())\n\t\t\t\t\t\t.toList();\n\t\t\t\t\treturn GetPromptResult.builder(messages).build();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (result instanceof PromptMessage) {\n\t\t\t// If the result is a single PromptMessage, wrap it in a list\n\t\t\treturn GetPromptResult.builder(List.of((PromptMessage) result)).build();\n\t\t}\n\t\telse if (result instanceof String) {\n\t\t\t// If the result is a simple string, create a single assistant message with\n\t\t\t// that content\n\t\t\treturn GetPromptResult.builder(List.of(PromptMessage\n\t\t\t\t.builder(McpSchema.Role.ASSISTANT, McpSchema.TextContent.builder((String) result).build())\n\t\t\t\t.build())).build();\n\t\t}\n\n\t\tthrow new IllegalArgumentException(\n\t\t\t\t\"Unsupported result type: \" + (result != null ? result.getClass().getName() : \"null\"));\n\t}\n\n\t/**\n\t * Abstract builder for creating prompt method callback instances.\n\t *\n\t * @param <B> The builder type\n\t * @param <T> The callback type\n\t */\n\tprotected abstract static class AbstractBuilder<B extends AbstractBuilder<B, T>, T extends AbstractMcpPromptMethodCallback> {\n\n\t\tprotected Method method;\n\n\t\tprotected Object bean;\n\n\t\tprotected Prompt prompt;\n\n\t\t/**","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/AbstractMcpPromptMethodCallback.java#L390-L426","documentation":"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.","triggerScenarios":"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.","commonSituations":"Returning a domain object assuming auto-serialization; returning Optional.of(text); methods refactored to return custom result wrappers; forgetting that null returns are rejected.","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."],"exampleFix":"// before\n@McpPrompt(name = \"summary\")\npublic Summary summarize(String text) { return new Summary(text); }\n// after\n@McpPrompt(name = \"summary\")\npublic GetPromptResult summarize(String text) {\n    return GetPromptResult.builder(List.of(PromptMessage.builder(McpSchema.Role.ASSISTANT,\n        McpSchema.TextContent.builder(buildSummary(text)).build()).build())).build();\n}","handlingStrategy":"type-guard","validationCode":"boolean hasSupportedPromptReturnType(Method m) {\n    Class<?> r = m.getReturnType();\n    return GetPromptResult.class.isAssignableFrom(r) || String.class.isAssignableFrom(r)\n        || PromptMessage.class.isAssignableFrom(r) || List.class.isAssignableFrom(r);\n}","typeGuard":"Object ensurePromptResult(Object result) {\n    if (result == null) return GetPromptResult.builder(List.of()).build();\n    if (result instanceof GetPromptResult || result instanceof String\n        || result instanceof PromptMessage || result instanceof List) return result;\n    throw new IllegalStateException(\"Unsupported prompt return type: \" + result.getClass());\n}","tryCatchPattern":"try {\n    GetPromptResult r = callback.apply(exchange, request);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unsupported result type\")) {\n        log.error(\"Fix the @McpPrompt method return type\", e);\n        return GetPromptResult.builder(List.of()).build();\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["mcp","return-type","unsupported-type","result-conversion"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}