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

A @McpPrompt-annotated method registered with the sync MCP prompt callback returns a type the framework cannot convert into a prompt result. The library validates the method's return type against a whitelist (GetPromptResult, List, PromptMessage, String) and throws IllegalArgumentException when none match. This fails fast at registration/startup rather than at request time.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java:151

		}
	}

	@Override
	protected boolean isSupportedExchangeOrContextType(Class<?> paramType) {
		return (McpSyncServerExchange.class.isAssignableFrom(paramType)
				|| 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 SyncMcpPromptMethodCallback instances.
	 * <p>
	 * This builder provides a fluent API for constructing SyncMcpPromptMethodCallback
	 * instances with the required parameters.

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Change the method's return type to GetPromptResult, List<PromptMessage>, List<String>, PromptMessage, or String.
  2. Wrap custom message data in PromptMessage with role and content (TextContent or EmbeddedResource).
  3. If the result is async/reactive, move to the async callback variant or block/convert to a sync type before returning.
  4. For lists of arbitrary strings, return List<String> which the framework converts into message content.

Example fix

// before
@McpPrompt(description = "greet")
public GreetingDto greet(String name) {
    return new GreetingDto("Hello " + name);
}

// after
@McpPrompt(description = "greet")
public String greet(String name) {
    return "Hello " + name;
}
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasValidPromptReturnType(Method m) {
    Class<?> r = m.getReturnType();
    return GetPromptResult.class.isAssignableFrom(r) || List.class.isAssignableFrom(r)
        || PromptMessage.class.isAssignableFrom(r) || String.class.isAssignableFrom(r);
}
// assert hasValidPromptReturnType(promptMethod) before registration;

Try / catch

try {
    server.addPrompt(promptSpec);
} catch (IllegalArgumentException e) {
    log.error("Prompt method signature invalid: {}", e.getMessage());
    throw new IllegalStateException("Fix @McpPrompt return type", e);
}

Prevention

When it happens

Trigger: Registering a prompt method (e.g. via McpServerFeatures or the annotations auto-config) whose return type is a POJO, CompletableFuture, Optional, custom wrapper, or primitive not on the allowed list; validateReturnType checks GetPromptResult/List/PromptMessage/String assignability and throws otherwise.

Common situations: Returning a custom DTO class directly; forgetting to wrap messages in PromptMessage; returning reactor Mono/Flux in a sync callback; copy-pasting a method that worked as a tool (where return types are broader) into a @McpPrompt method.

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


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/dbbfebc5ffd34538. Report an issue: GitHub.