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
- Call .bean(...) with the object instance declaring the @McpComplete method before build()
- 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
- Pass the Spring bean instance (via ApplicationContext.getBean) when registering manually
- Check for null bean resolution before building; assert the annotated class is a registered bean
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
- Bean must not be null
- Bean must not be null
- Method must not be null
- Updated resources list must not be null
- Bean must not be null
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/2afdff1a2229c3d5.
Report an issue: GitHub.