alibaba/spring-ai-alibaba · error · IllegalStateException
selectionModel is required
Error message
selectionModel is required
What it means
ToolSelectionInterceptor.build() performs a post-configuration check and throws IllegalStateException when no selection model (a ChatModel used to decide which tools to keep) was supplied. Without a model the interceptor cannot function, so building is refused.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/toolselection/ToolSelectionInterceptor.java:240
throw new IllegalArgumentException("maxTools must be > 0");
}
this.maxTools = maxTools;
return this;
}
public Builder alwaysInclude(Set<String> alwaysInclude) {
this.alwaysInclude = alwaysInclude;
return this;
}
public Builder alwaysInclude(String... toolNames) {
this.alwaysInclude = new HashSet<>(Arrays.asList(toolNames));
return this;
}
public ToolSelectionInterceptor build() {
if (selectionModel == null) {
throw new IllegalStateException("selectionModel is required");
}
return new ToolSelectionInterceptor(this);
}
}
}
View on GitHub (pinned to f82da0b50f)
Solutions
- Call the builder's selection-model setter with a ChatModel instance before build()
- Ensure the ChatModel bean is available in the Spring context / application profile
- Reorder construction so the model is created before the interceptor is built
Example fix
// before
ToolSelectionInterceptor.builder().maxTools(3).build(); // IllegalStateException
// after
ToolSelectionInterceptor.builder()
.selectionModel(chatModel)
.maxTools(3)
.build(); Defensive patterns
Strategy: validation
Validate before calling
assert chatModel != null : "selectionModel must be set before ToolSelectionInterceptor.build()";
Type guard
boolean canBuild(ToolSelectionInterceptor.Builder b) { return b != null && selectionModel != null; } Try / catch
try { interceptor = b.build(); } catch (IllegalStateException e) { throw new BeanInitializationException("ToolSelectionInterceptor misconfigured", e); } Prevention
- Always set the selection model immediately after obtaining the builder
- Use constructor/Spring injection so the ChatModel cannot be null
- Add a startup smoke test that builds all interceptors
When it happens
Trigger: Calling ToolSelectionInterceptor.builder().build() without ever calling the builder method that sets the selectionModel.
Common situations: Constructing the builder from config where the model bean is missing or null; copying interceptor setup code and dropping the model call; the model is conditionally injected and absent in the active profile.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- maxTools must be > 0
- LoopAgent must have only one subAgent, please use subAgent()
- Sub-agents must be BaseAgent
- Routing flow requires a ChatModel for decision making
- At least one fallback model must be specified
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/f9797953f503f669.
Report an issue: GitHub.