alibaba/spring-ai-alibaba · error · IllegalArgumentException
maxAttempts must be greater than or equal to 1
Error message
maxAttempts must be greater than or equal to 1
What it means
ModelRetryInterceptor.Builder.maxAttempts(int) validates that the maximum attempt count is at least 1 (the count includes the first call). Passing 0 or a negative value throws IllegalArgumentException at builder time, before any model call happens.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/modelretry/ModelRetryInterceptor.java:300
@Override
public String getName() {
return "ModelRetry";
}
public static class Builder {
private int maxAttempts = 3;
private long initialDelay = 1000;
private long maxDelay = 30000;
private double backoffMultiplier = 2.0;
private Predicate<Exception> retryableExceptionPredicate = Builder::isRetryableException;
/**
* Set the maximum number of retries (including the first call).
* @param maxAttempts The maximum number of attempts must be >= 1.
*/
public Builder maxAttempts(int maxAttempts) {
if (maxAttempts < 1) {
throw new IllegalArgumentException("maxAttempts must be greater than or equal to 1");
}
this.maxAttempts = maxAttempts;
return this;
}
/**
* Set the initial retry delay (milliseconds).
* @param initialDelay Initial delay time, in milliseconds
*/
public Builder initialDelay(long initialDelay) {
if (initialDelay < 0) {
throw new IllegalArgumentException("initialDelay must be greater than or equal to 0.");
}
this.initialDelay = initialDelay;
return this;
}
/**View on GitHub (pinned to f82da0b50f)
Solutions
- Pass a value >= 1; remember 1 means the initial call with no retries, 3 means up to 2 retries.
- Clamp or validate configuration at startup: Math.max(1, configuredMaxAttempts).
- If you want retries disabled entirely, use maxAttempts(1) rather than 0.
Example fix
// before
int attempts = Integer.parseInt(props.getProperty("retry.maxAttempts", "0"));
ModelRetryInterceptor.builder().maxAttempts(attempts).build();
// after
int attempts = Math.max(1, Integer.parseInt(props.getProperty("retry.maxAttempts", "3")));
ModelRetryInterceptor.builder().maxAttempts(attempts).build(); Defensive patterns
Strategy: validation
Validate before calling
public static ModelRetryInterceptor buildRetry(int maxAttempts) {
if (maxAttempts < 1) throw new IllegalArgumentException("maxAttempts must be >= 1 (1 = no retries)");
return ModelRetryInterceptor.builder().maxAttempts(maxAttempts).build();
} Try / catch
try {
builder.maxAttempts(cfg.maxAttempts());
} catch (IllegalArgumentException e) {
log.warn("Invalid maxAttempts in config ({}), defaulting to 3", cfg.maxAttempts());
builder.maxAttempts(3);
} Prevention
- Remember the semantic: maxAttempts counts total attempts including the first; 1 disables retries.
- Clamp external config values (Math.max(1, value)) before passing to the builder.
- Cover builder configuration in unit tests so bad defaults surface in CI.
When it happens
Trigger: Calling ModelRetryInterceptor.builder().maxAttempts(0) or maxAttempts(negative) — commonly from an external config value (properties file, env var) that is unset, 0, or mis-parsed.
Common situations: Binding maxAttempts from application.properties/yaml where a 'retries: 0' convention was assumed; integer parse failures defaulting to 0; arithmetic producing a negative value; thinking the setting means 'extra retries' rather than total attempts.
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
- initialDelay must be greater than or equal to 0.
- maxAttempts must be >= 1
- maxRetries must be >= 0
- maxContentLength must be positive
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/cde343dc395f2de2.
Report an issue: GitHub.