spring-projects/spring-ai · error · McpElicitationMethodException

Error invoking elicitation method:

Error message

Error invoking elicitation method: 

What it means

SyncMcpElicitationMethodCallback.apply() wraps any exception thrown while reflectively invoking a @McpElicitation-annotated method into an McpElicitationMethodException. The original cause (e.g. a user-code NPE or return-type mismatch) is preserved as the cause. It signals that the elicitation callback method itself failed during execution, not that the MCP protocol exchange failed.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/elicitation/SyncMcpElicitationMethodCallback.java:98

					.build();
			}
			else if (this.method.getReturnType().isAssignableFrom(ElicitResult.class)) {
				// If the method returns ElicitResult, return it directly
				return (ElicitResult) result;

			}
			else {

				// TODO add support for methods returning simple types or Objects of
				// elicitation schema type.

				throw new IllegalStateException("Method must return ElicitResult or StructuredElicitResult: "
						+ this.method.getName() + " in " + this.method.getDeclaringClass().getName() + " returns "
						+ this.method.getReturnType().getName());
			}
		}
		catch (Exception e) {
			throw new McpElicitationMethodException("Error invoking elicitation method: " + this.method.getName(), e);
		}
	}

	/**
	 * Validates that the method return type is compatible with the elicitation callback.
	 * @param method The method to validate
	 * @throws IllegalArgumentException if the return type is not compatible
	 */
	@Override
	protected void validateReturnType(Method method) {
		Class<?> returnType = method.getReturnType();

		if (!ElicitResult.class.isAssignableFrom(returnType)
				&& !StructuredElicitResult.class.isAssignableFrom(returnType)) {
			throw new IllegalArgumentException("Method must return ElicitResult: " + method.getName() + " in "
					+ method.getDeclaringClass().getName() + " returns " + returnType.getName());
		}
	}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Inspect the cause chain (getCause()) of the McpElicitationMethodException to find the real failure in your handler method
  2. Ensure the annotated method's return type is ElicitResult or StructuredElicitResult
  3. Add null/argument checks inside your elicitation handler before using the request
  4. Fix visibility of the annotated method (must be accessible for reflection)

Example fix

// before
@McpElicitation(clients = "client1")
public String askUser(ElicitRequest request) { return request.message(); }
// after
@McpElicitation(clients = "client1")
public ElicitResult askUser(ElicitRequest request) {
    if (request == null) { throw new IllegalArgumentException("request required"); }
    return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of());
}
Defensive patterns

Strategy: try-catch

Validate before calling

for (Method m : handler.getClass().getDeclaredMethods()) {
    if (m.isAnnotationPresent(McpElicitation.class)
            && !ElicitResult.class.isAssignableFrom(m.getReturnType())
            && !StructuredElicitResult.class.isAssignableFrom(m.getReturnType())) {
        throw new IllegalStateException(m.getName() + " must return ElicitResult or StructuredElicitResult");
    }
}

Try / catch

try {
    elicitationCallback.apply(exchange, request);
} catch (McpElicitationMethodException e) {
    logger.error("elicitation handler failed", e.getCause());
    return new ElicitResult(ElicitResult.Action.DENY, Map.of());
}

Prevention

When it happens

Trigger: Registering a @McpElicitation handler method whose body throws at runtime; the method returns a type other than ElicitResult/StructuredElicitResult; reflection on the method fails (IllegalAccessException).

Common situations: User handler code dereferences a null request argument; an annotated method with the wrong return type slipped past compile-time checks (e.g. raw types); tests like testNullRequest pass a null request and the handler throws.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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