spring-projects/spring-ai · error · IllegalArgumentException

Method must have at least 1 parameter (CreateMessageRequest)

Error message

Method must have at least 1 parameter (CreateMessageRequest): {methodName} in {className} has {paramCount} parameters

What it means

This error means a method registered as an MCP sampling callback takes no parameters, but the framework requires at least one. The sampling protocol invokes the callback with a CreateMessageRequest, so the callback method must accept it as its (first) argument. AbstractMcpSamplingMethodCallback.validateParameters() enforces this at registration time and throws IllegalArgumentException.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/sampling/AbstractMcpSamplingMethodCallback.java:93

	 * This method should be implemented by subclasses to handle specific return type
	 * validation.
	 * @param method The method to validate
	 * @throws IllegalArgumentException if the return type is not compatible
	 */
	protected abstract void validateReturnType(Method method);

	/**
	 * Validates method parameters. This method provides common validation logic and
	 * delegates exchange type checking to subclasses.
	 * @param method The method to validate
	 * @throws IllegalArgumentException if the parameters are not compatible
	 */
	protected void validateParameters(Method method) {
		Parameter[] parameters = method.getParameters();

		// Check parameter count - must have at least 1 parameter
		if (parameters.length < 1) {
			throw new IllegalArgumentException(
					"Method must have at least 1 parameter (CreateMessageRequest): " + method.getName() + " in "
							+ method.getDeclaringClass().getName() + " has " + parameters.length + " parameters");
		}

		// Check parameter types
		if (parameters.length == 1) {
			// Single parameter must be CreateMessageRequest
			if (!CreateMessageRequest.class.isAssignableFrom(parameters[0].getType())) {
				throw new IllegalArgumentException("Single parameter must be of type CreateMessageRequest: "
						+ method.getName() + " in " + method.getDeclaringClass().getName() + " has parameter of type "
						+ parameters[0].getType().getName());
			}
		}
		else {
			// TODO: Support for multiple parameters corresponding to CreateMessageRequest
			// fields
			// For now, we only support the single parameter version
			throw new IllegalArgumentException(

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Add a single parameter of type io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest to the annotated method
  2. If the method was not meant to be a sampling handler, remove the sampling annotation from it
  3. Rebuild/re-register the MCP server and confirm the callback validates successfully

Example fix

// before
@McpSampling
public String sample() { return "reply"; }
// after
@McpSampling
public String sample(CreateMessageRequest request) { return "reply: " + request.messages(); }
Defensive patterns

Strategy: validation

Validate before calling

for (Method m : clazz.getDeclaredMethods()) {
    if (m.isAnnotationPresent(McpSampling.class)
            && m.getParameterCount() < 1) {
        throw new IllegalStateException("Sampling method " + m.getName()
            + " must declare a CreateMessageRequest parameter");
    }
}

Type guard

boolean isValidSamplingMethod(Method m) {
    return m.getParameterCount() >= 1
        && CreateMessageRequest.class.isAssignableFrom(m.getParameterTypes()[0]);
}

Try / catch

try {
    registerSamplingCallback(method);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("at least 1 parameter")) {
        log.error("Bad sampling signature on {}: {}", method, e.getMessage());
    } else { throw e; }
}

Prevention

When it happens

Trigger: Registering a @McpSampling (sampling) handler method whose signature has zero parameters, e.g. `void mySampler()` annotated for sampling; the validation runs in validateMethod during callback construction.

Common situations: Developers copy an unannotated helper method and add the sampling annotation without changing its signature; they assume the request is optional or injected elsewhere; refactoring removed the parameter but left the annotation in place.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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