spring-projects/spring-ai · error · IllegalArgumentException

Bean must not be null

Error message

Bean must not be null

What it means

Builder validation error: the AbstractMcpCompleteMethodCallback builder was built without setting the target bean that owns the completion method. validate() rejects a null bean because the callback needs it to invoke the method reflectively.

Source

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

		 * @param uriTemplateManagerFactory The URI template manager factory
		 * @return This builder
		 */
		@SuppressWarnings("unchecked")
		public T uriTemplateManagerFactory(McpUriTemplateManagerFactory uriTemplateManagerFactory) {
			this.uriTemplateManagerFactory = uriTemplateManagerFactory;
			return (T) this;
		}

		/**
		 * Validate the builder state.
		 * @throws IllegalArgumentException if the builder state is invalid
		 */
		protected void validate() {
			if (this.method == null) {
				throw new IllegalArgumentException("Method must not be null");
			}
			if (this.bean == null) {
				throw new IllegalArgumentException("Bean must not be null");
			}
			if ((this.prompt == null || this.prompt.isEmpty()) && (this.uri == null || this.uri.isEmpty())) {
				throw new IllegalArgumentException("Either prompt or uri must be provided");
			}
			if ((this.prompt != null && !this.prompt.isEmpty()) && (this.uri != null && !this.uri.isEmpty())) {
				throw new IllegalArgumentException("Only one of prompt or uri can be provided");
			}
			if (this.uriTemplateManagerFactory == null) {
				this.uriTemplateManagerFactory = new DefaultMcpUriTemplateManagerFactory();
			}
		}

		/**
		 * Build the callback.
		 * @return A new callback instance
		 */
		public abstract R build();

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Call .bean(...) with the object instance declaring the @McpComplete method before build()
  2. Verify the annotated class is registered as a Spring bean so the scanner can pass it to the builder

Example fix

// before
var callback = builder().method(method).prompt("lang").build();
// after
var callback = builder().bean(completionService).method(method).prompt("lang").build();
Defensive patterns

Strategy: validation

Validate before calling

if (targetBean == null) throw new IllegalStateException("Completion callback builder requires .bean(...) before build()");

Type guard

boolean readyToBuild = targetBean != null && methodRef != null;

Try / catch

try {
    return builder().bean(bean).method(m).build();
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("Bean must not be null")) { /* ensure bean was set / resolved from Spring context */ }
    throw e;
}

Prevention

When it happens

Trigger: Calling build() on the completion callback builder without invoking .bean(...) with the Spring bean / object holding the annotated method.

Common situations: Manual callback registration outside of Spring context (no bean supplied); bean resolution returning null because the class was not registered as a bean.

Related errors


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