alibaba/spring-ai-alibaba · error · IllegalArgumentException
maxRetries must be >= 0
Error message
maxRetries must be >= 0
What it means
ToolRetryInterceptor's deprecated Builder.maxRetries(int) validates that the retry count is non-negative, throwing IllegalArgumentException when a negative value is passed. maxRetries counts extra retries, so total attempts = maxRetries + 1. The library rejects negative numbers because a negative retry count is meaningless.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/toolretry/ToolRetryInterceptor.java:195
* @param maxAttempts total attempts (initial call plus retries)
*/
public Builder maxAttempts(int maxAttempts) {
if (maxAttempts < 1) {
throw new IllegalArgumentException("maxAttempts must be >= 1");
}
this.maxAttempts = maxAttempts;
return this;
}
/**
* Set the maximum number of retries (excluding the first call).
* @param maxRetries number of retries; total attempts will be {@code maxRetries + 1}
* @deprecated use {@link #maxAttempts(int)} instead, which counts the initial call
*/
@Deprecated
public Builder maxRetries(int maxRetries) {
if (maxRetries < 0) {
throw new IllegalArgumentException("maxRetries must be >= 0");
}
this.maxAttempts = maxRetries + 1;
return this;
}
public Builder toolNames(Set<String> toolNames) {
this.toolNames = toolNames;
return this;
}
public Builder toolName(String toolName) {
if (this.toolNames == null) {
this.toolNames = new HashSet<>();
}
this.toolNames.add(toolName);
return this;
}
View on GitHub (pinned to f82da0b50f)
Solutions
- Pass 0 to disable retries instead of a negative number
- Prefer the non-deprecated maxAttempts(int) builder method, which counts the initial call (total attempts = maxAttempts)
- Validate the configured value before building the interceptor
Example fix
// before ToolRetryInterceptor.builder().maxRetries(-1).build(); // after ToolRetryInterceptor.builder().maxAttempts(1).build(); // 1 total attempt, no retries
Defensive patterns
Strategy: validation
Validate before calling
if (retries < 0) throw new IllegalArgumentException("Configure retries >= 0, or use maxAttempts >= 1"); Type guard
boolean isValidRetryCount(int n) { return n >= 0; } Try / catch
try { b.maxRetries(n); } catch (IllegalArgumentException e) { b.maxAttempts(Math.max(1, n + 1)); } Prevention
- Use the non-deprecated maxAttempts(int) API, which counts the initial call
- Treat 0 as the 'disable retries' value, never -1
- Validate retry values when loading from config/env
When it happens
Trigger: Calling ToolRetryInterceptor.Builder.maxRetries(-1) (or any negative int) instead of using the replacement maxAttempts(int).
Common situations: Computing the retry count from config or environment variables that may be negative or uninitialized; migrating code and passing -1 as a sentinel for 'no retries' instead of 0.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- At least one fallback model must be specified
- maxAttempts must be greater than or equal to 1
- maxAttempts must be >= 1
- maxTools must be > 0
- maxParallelTools must be at least 1
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/a6703353185fcd71.
Report an issue: GitHub.