spring-projects/spring-ai · error · IllegalStateException
argumentType is required
Error message
argumentType is required
What it means
AugmentedToolCallbackProvider.Builder.build() validates required fields before creating the provider. If argumentType was never set it throws IllegalStateException("argumentType is required"), because the provider needs the argument type to generate tool schemas and bind arguments. The argumentConsumer check follows immediately.
Source
Thrown at spring-ai-model/src/main/java/org/springframework/ai/tool/augment/AugmentedToolCallbackProvider.java:147
/**
* Sets whether to remove extra arguments after processing
* @param removeExtraArgumentsAfterProcessing true to remove extra arguments
* @return this builder
*/
public Builder<T> removeExtraArgumentsAfterProcessing(boolean removeExtraArgumentsAfterProcessing) {
this.removeExtraArgumentsAfterProcessing = removeExtraArgumentsAfterProcessing;
return this;
}
/**
* 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 NullAwayView on GitHub (pinned to 98a7beda4f)
Solutions
- Call .argumentType(MyArguments.class) on the builder before build()
- Also verify .argumentConsumer(...) and .delegate(...) or .toolObject(...) are set as required
- Use the typed builder generic consistently so argumentType can be derived/checked at compile time
Example fix
// before
var provider = AugmentedToolCallbackProvider.builder()
.argumentConsumer(args -> handle(args))
.build();
// after
var provider = AugmentedToolCallbackProvider.builder()
.argumentType(MyArgs.class)
.argumentConsumer(args -> handle(args))
.build(); Defensive patterns
Strategy: validation
Validate before calling
// Validate builder inputs before build()
if (argsType == null) throw new IllegalStateException("argumentType must be set before build()");
if (argsConsumer == null) throw new IllegalStateException("argumentConsumer must be set before build()"); Try / catch
AugmentedToolCallbackProvider<MyArgs> provider;
try {
provider = AugmentedToolCallbackProvider.<MyArgs>builder()
.argumentType(MyArgs.class)
.argumentConsumer(this::handle)
.build();
} catch (IllegalStateException e) {
// missing builder field (argumentType/argumentConsumer/etc.)
throw new IllegalArgumentException("Incomplete AugmentedToolCallbackProvider builder: " + e.getMessage(), e);
} Prevention
- Always set argumentType first, then argumentConsumer, in builder chains
- Centralize provider construction in one factory method
- Add a smoke test that builds every provider at startup
When it happens
Trigger: Calling AugmentedToolCallbackProvider.builder()...build() without invoking .argumentType(SomeClass.class), or losing the builder value through conditional code paths; argumentType must be set on the builder before build().
Common situations: Copied builder snippets that omit argumentType, generic code where the type parameter T wasn't reflected into the builder, or refactoring that removed the argumentType call while keeping argumentConsumer.
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
- Only outputType or outputJsonSchema can be set, not both.
- Either outputType or outputJsonSchema must be set.
- Either vectorStore or jedisClient must be provided
- MessageEndpoint must be set
- DataSource must be set (either via dataSource() or jdbcTempl
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/907b2879086e4b87.
Report an issue: GitHub.