spring-projects/spring-ai · error · IllegalArgumentException

Bean must not be null

Error message

Bean must not be null

What it means

Thrown by AbstractMcpPromptListChangedMethodCallback.Builder.validate() when the builder's `bean` field is null at build time. The callback invokes the handler method on this bean instance (this.method.invoke(this.bean, args)); without a target instance there is no receiver for the reflective call. Validation runs eagerly in build() to fail fast on misconfiguration.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/changed/prompt/AbstractMcpPromptListChangedMethodCallback.java:211

		 * @param promptListChanged The prompt list changed annotation
		 * @return This builder
		 */
		@SuppressWarnings("unchecked")
		public T promptListChanged(McpPromptListChanged promptListChanged) {
			// No additional configuration needed from the annotation at this time
			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");
			}
		}

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

	}

}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Call bean(Object) on the builder with the instance that declares the prompt-list-changed handler method before build().
  2. Ensure the handler class is a registered Spring bean (@Component or @Bean definition) so the framework can inject a non-null instance.
  3. Add a startup assertion/bean-exists check if the handler bean is resolved dynamically.

Example fix

// before
AsyncMcpPromptListChangedMethodCallback.builder()
    .method(handlerMethod)
    .build(); // bean == null
// after
AsyncMcpPromptListChangedMethodCallback.builder()
    .method(handlerMethod)
    .bean(myPromptHandler)
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if (handlerBean == null) {
    throw new IllegalStateException("handler bean not injected — check Spring registration");
}
AsyncMcpPromptListChangedMethodCallback.builder().bean(handlerBean).method(handler).build();

Try / catch

try {
    callback = builder.build();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Bean must not be null")) {
        throw new ConfigurationException("Builder missing bean(Object) — supply the handler instance", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling build() without calling bean(Object) (or the bean field not being set by the constructor path used). Occurs when wiring the callback manually and forgetting to supply the handler instance, or when dependency injection produced a null bean.

Common situations: Manual builder wiring in tests; the annotated handler bean not being registered in the Spring context so injection yields null; constructing the builder from code where the handler instance is resolved conditionally and can be null.

Related errors


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