quarkusio/quarkus · error · IllegalArgumentException
`%s` must be greater than or equal to zero
Error message
`%s` must be greater than or equal to zero
What it means
The second branch of Validation.validateTimeout rejects negative Duration values for Redis command timeouts/TTLs. Redis time arguments must be non-negative, so the Quarkus Redis datasource throws IllegalArgumentException before issuing the command.
Source
Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/Validation.java:118
static void validateLongitude(double longitude) {
if (longitude < -180 || longitude > 180) {
throw new IllegalArgumentException("The longitude must be in [-180, 180]");
}
}
static void validateLatitude(double latitude) {
if (latitude < -85.05112878 || latitude > 85.05112878) {
throw new IllegalArgumentException("The latitude must be in [85.05112878, 85.05112878]");
}
}
public static void validateTimeout(Duration value, String name) {
if (value == null) {
throw new IllegalArgumentException(String.format("`%s` must not be `null`", name));
}
if (value.isNegative()) {
throw new IllegalArgumentException(String.format("`%s` must be greater than or equal to zero", name));
}
}
public static void positive(double amount, String name) {
if (amount <= 0) {
throw new IllegalArgumentException(String.format("`%s` must be greater than zero`", name));
}
}
public static void positiveOrZero(double amount, String name) {
if (amount < 0) {
throw new IllegalArgumentException(String.format("`%s` must be greater or equal to zero", name));
}
}
public static void isBit(int b, String name) {
if (b != 0 && b != 1) {
throw new IllegalArgumentException(String.format("`%s` must be either `0` or `1`", name));View on GitHub (pinned to e1c734241f)
Solutions
- Reorder Duration.between arguments so it is (start, end) not (end, start)
- Clamp with a negative check: Duration negative-safe value = value.isNegative() ? Duration.ZERO : value
- Fix the negative value in the configuration file
- If the intent is 'no expiry', skip the timeout parameter entirely instead of passing a negative duration
Example fix
// before Duration age = Duration.between(now, createdAt); // negative redis.setTimeout(age); // after Duration age = Duration.between(createdAt, now); redis.setTimeout(age.isNegative() ? Duration.ZERO : age);
Defensive patterns
Strategy: validation
Validate before calling
if (duration != null && duration.isNegative()) throw new IllegalArgumentException("negative duration: " + duration);
Duration safe = duration.isNegative() ? Duration.ZERO : duration; Try / catch
try { redis.setTimeout(d); } catch (IllegalArgumentException e) { log.warn("Negative timeout rejected: {}", e.getMessage()); } Prevention
- Check Duration.between argument order (start, end)
- Clamp negative computed durations to ZERO
- Lint configuration files for negative duration values
- Add assertions on computed durations in dev profile
When it happens
Trigger: Passing a negative Duration produced by subtracting a later timestamp from an earlier one (Duration.between with reversed order) or a misconfigured property like quarkus.redis.timeout=-1s, into a Redis command timeout parameter.
Common situations: Duration.between(creationTime, now) accidentally reversed; clock skew when computing expiry deltas; YAML/properties files containing negative values copied from tuning notes; math like now - expiry instead of expiry - now.
Related errors
- `count` must be strictly positive
- `timeout` must be positive
- `timeout` must not be `null`
- `timestamp` must not be `null`
- Channel cannot be blank
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f084764a27006591.
Report an issue: GitHub.