spring-projects/spring-ai · error · IllegalStateException
Either delegate or toolObject must be set
Error message
Either delegate or toolObject must be set
What it means
build() requires at least one tool source: either a delegate ToolCallback/ToolCallbackProvider or a toolObject with @Tool methods. If neither is set the provider would produce no tools, so it throws an IllegalStateException immediately.
Source
Thrown at spring-ai-model/src/main/java/org/springframework/ai/tool/augment/AugmentedToolCallbackProvider.java:158
/**
* Builds the {@link AugmentedToolCallbackProvider} instance.
* @return the built instance
* @throws IllegalStateException if required fields are not set
*/
public AugmentedToolCallbackProvider<T> build() {
if (this.argumentType == null) {
throw new IllegalStateException("argumentType is required");
}
if (this.argumentConsumer == null) {
throw new IllegalStateException("argumentConsumer is required");
}
if (this.delegate != null && this.toolObject != null) {
throw new IllegalStateException("Cannot set both delegate and toolObject");
}
if (this.delegate == null && this.toolObject == null) {
throw new IllegalStateException("Either delegate or toolObject must be set");
}
if (this.toolObject != null) {
return new AugmentedToolCallbackProvider<>(this.toolObject, this.argumentType, this.argumentConsumer,
this.removeExtraArgumentsAfterProcessing);
}
else if (this.delegate != null) { // Redundant if condition to please NullAway
return new AugmentedToolCallbackProvider<>(this.delegate, this.argumentType, this.argumentConsumer,
this.removeExtraArgumentsAfterProcessing);
}
else {
throw new IllegalStateException();
}
}
}
}View on GitHub (pinned to 98a7beda4f)
Solutions
- Set a source: call .toolObject(new MyTools()) or .delegate(toolCallbackProvider) on the builder.
- Verify configuration/properties actually resolve to a non-null tool source before building.
- If tools may legitimately be absent, skip creating the provider instead of building an empty one.
Example fix
// before
var builder = AugmentedToolCallbackProvider.builder()
.argumentType(Args.class)
.argumentConsumer(a -> a);
if (toolsEnabled) { /* source never set */ }
var provider = builder.build();
// after
var builder = AugmentedToolCallbackProvider.builder()
.argumentType(Args.class)
.argumentConsumer(a -> a);
if (toolsEnabled) {
builder.toolObject(new MyTools());
var provider = builder.build();
} Defensive patterns
Strategy: validation
Validate before calling
if (toolSource == null) {
throw new IllegalArgumentException("Provide a toolObject or delegate before building AugmentedToolCallbackProvider");
} Type guard
if (toolObject == null && delegate == null) return null; // skip provider creation
Try / catch
try { provider = builder.build(); } catch (IllegalStateException e) { log.warn("No tool source configured, skipping augmented tools"); provider = null; } Prevention
- Make tool sources mandatory constructor/bean parameters so they cannot silently be null.
- Log configuration resolution results when building providers from properties.
When it happens
Trigger: Calling AugmentedToolCallbackProvider.builder().argumentType(X.class).argumentConsumer(c -> c).build() without calling .delegate(...) or .toolObject(...).
Common situations: Conditional configuration where the source assignment branch was skipped; bean definitions parameterized by properties where the source property is empty/null.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- argumentConsumer is required
- Either outputType or outputJsonSchema must be set.
- argumentType is required
- Cannot set both delegate and toolObject
- Bean must not be null
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/56616900531b7807.
Report an issue: GitHub.