apache/seatunnel · error · IllegalArgumentException
Retry times must be greater than 0
Error message
Retry times must be greater than 0
What it means
RetryUtils.retryWithException validates that the caller-supplied RetryMaterial has non-negative retryTimes before attempting execution. A negative value is rejected with IllegalArgumentException 'Retry times must be greater than 0'. Note the check is < 0, so 0 passes validation (meaning a single attempt, no retries) despite the message wording.
Source
Thrown at seatunnel-common/src/main/java/org/apache/seatunnel/common/utils/RetryUtils.java:41
@Slf4j
public class RetryUtils {
/**
* Execute the given execution with retry
*
* @param execution execution to execute
* @param retryMaterial retry material, defined the condition to retry
* @param <T> result type
* @return result of execution
*/
public static <T> T retryWithException(
Execution<T, Exception> execution, RetryMaterial retryMaterial) throws Exception {
final RetryCondition<Exception> retryCondition = retryMaterial.getRetryCondition();
final int retryTimes = retryMaterial.getRetryTimes();
if (retryMaterial.getRetryTimes() < 0) {
throw new IllegalArgumentException("Retry times must be greater than 0");
}
Exception lastException;
int i = 0;
do {
i++;
try {
return execution.execute();
} catch (Exception e) {
lastException = e;
if (retryCondition != null && !retryCondition.canRetry(e)) {
if (retryMaterial.shouldThrowException()) {
throw e;
}
} else {
// Otherwise it is retriable and we should retry
String attemptMessage =
"Failed to execute due to {}. Retrying attempt ({}/{}) after backoff of {} ms";
if (retryMaterial.getSleepTimeMillis() > 0) {View on GitHub (pinned to cf67b549a7)
Solutions
- Set retryTimes to a positive integer (>=1) in the RetryMaterial builder or config
- If retries should be disabled, use retryTimes 0 rather than a negative value
- Validate/clamp the value when loading it from user configuration before constructing RetryMaterial
- If unlimited-ish behavior is needed, pass a large retry count with an appropriate retry backoff
Example fix
// before RetryMaterial material = RetryMaterial.builder().retryTimes(-1).build(); // after RetryMaterial material = RetryMaterial.builder().retryTimes(3).build();
Defensive patterns
Strategy: validation
Validate before calling
int retryTimes = config.getInt("retry-times");
if (retryTimes < 0) {
throw new IllegalArgumentException("retry-times must be >= 0, got: " + retryTimes);
} Try / catch
try {
return RetryUtils.retryWithException(execution, material);
} catch (IllegalArgumentException e) {
log.error("Invalid retry material: {}", e.getMessage());
throw e;
} Prevention
- Clamp config-derived retry counts to >= 0 at load time
- Use 0 (not -1) to mean 'no retries'
- Add unit tests for boundary config values
- Document valid ranges next to the config option
When it happens
Trigger: Constructing RetryMaterial (e.g. RetryMaterial.builder().retryTimes(-1)) or otherwise passing a negative retryTimes into retryWithException. Typically caused by misread configuration where a sentinel -1 was intended to mean 'infinite' or 'disabled'.
Common situations: Config file value parsed to -1 for retry count; user setting retry-times: -1 expecting unlimited retries; arithmetic producing a negative value from a subtraction on config values.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- COMMON_ILLEGAL_ARGUMENT
- retry.max-attempts must be >= 1.
- retry.backoff-ms must be >= 0.
- retry.backoff-max-ms must be >= effective retry.backoff-ms (
- ILLEGAL_ARGUMENT
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/3f51992ca399f5b5.
Report an issue: GitHub.