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

Unsupported result type

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.

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.

Appendix: 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)