spring-projects/spring-ai · error · McpCompleteMethodException

Error invoking complete method:

Error message

Error invoking complete method: 

What it means

When the reflective invocation of the user's @McpComplete method (this.method.invoke) throws — or the result conversion fails — apply() wraps the cause in McpCompleteMethodException with the message 'Error invoking complete method: <methodName>', preserving the original exception as the cause. This is the generic failure envelope for completion handler execution.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/SyncMcpCompleteMethodCallback.java:81

	@Override
	public CompleteResult apply(McpSyncServerExchange exchange, CompleteRequest request) {
		if (request == null) {
			throw new IllegalArgumentException("Request must not be null");
		}

		try {
			// Build arguments for the method call
			Object[] args = this.buildArgs(this.method, exchange, request);

			// Invoke the method
			this.method.setAccessible(true);
			Object result = this.method.invoke(this.bean, args);

			// Convert the result to a CompleteResult
			return convertToCompleteResult(result);
		}
		catch (Exception e) {
			throw new McpCompleteMethodException("Error invoking complete method: " + this.method.getName(), e);
		}
	}

	/**
	 * Converts the method result to a CompleteResult.
	 * @param result The method result
	 * @return The CompleteResult
	 */
	private CompleteResult convertToCompleteResult(Object result) {
		if (result == null) {
			return new CompleteResult(new CompleteCompletion(List.of(), 0, false));
		}

		if (result instanceof CompleteResult) {
			return (CompleteResult) result;
		}

		if (result instanceof CompleteCompletion) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Read the cause (e.getCause()) of McpCompleteMethodException to find the real failure inside your method
  2. Verify @McpComplete argument names match the method parameter names and buildArgs expectations
  3. Fix the root exception in the completion method (null checks, service availability)
  4. Ensure the return type is CompleteResult/CompleteCompletion/List<String>/String/Mono<T> so conversion succeeds

Example fix

// before
@McpComplete(name:="argx") public List<String> complete(String argument) { ... } // name mismatch -> binding failure
// after
@McpComplete(name:="argument") public List<String> complete(String argument) { ... }
Defensive patterns

Strategy: try-catch

Try / catch

try {
    return callback.apply(exchange, request);
} catch (McpCompleteMethodException e) {
    log.error("Completion method {} failed", e.getMessage(), e.getCause());
    return new CompleteResult(new CompleteCompletion(List.of(), 0, false));
}

Prevention

When it happens

Trigger: Any exception inside the annotated completion method (NPE, database error, assertion), the method not being accessible for reflection (IllegalAccessException), wrong argument binding, or convertToCompleteResult rejecting the result (see errors 105/106).

Common situations: Completion method throws because a downstream service is unavailable; argument name in @McpComplete annotation does not match a method parameter; security manager / module access blocking reflection; returning an unsupported type that fails conversion.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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