quarkusio/quarkus · error · IllegalArgumentException
`timeout` must not be `null`
Error message
`timeout` must not be `null`
What it means
SetArgs.ex(Duration) converts the duration to seconds and delegates to ex(long), but first rejects a null Duration. The Quarkus Redis client validates arguments eagerly to fail at the call site rather than at Redis. Null cannot represent an expiry duration.
Source
Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/string/SetArgs.java:49
* @return the current {@code GetExArgs}
*/
public SetArgs ex(long timeout) {
if (timeout <= 0) {
throw new IllegalArgumentException("`timeout` must be positive");
}
this.ex = timeout;
return this;
}
/**
* Sets the expiration.
*
* @param timeout expire time in seconds.
* @return the current {@code GetExArgs}
*/
public SetArgs ex(Duration timeout) {
if (timeout == null) {
throw new IllegalArgumentException("`timeout` must not be `null`");
}
return ex(timeout.toMillis() / 1000);
}
/**
* Sets the expiration time
*
* @param timestamp the timestamp
* @return the current {@code GetExArgs}
*/
public SetArgs exAt(long timestamp) {
this.exAt = timestamp;
return this;
}
/**
* Sets the expiration time
*View on GitHub (pinned to e1c734241f)
Solutions
- Provide a default: ex(duration != null ? duration : Duration.ofSeconds(60))
- Build args conditionally and skip ex() when duration == null
- Switch to the long-based ex(long seconds) only after the duration has been resolved and null-checked
Example fix
// before
Duration ttl = config.ttl(); // may be null
SetArgs args = SetArgs.args().ex(ttl); // throws
// after
Duration ttl = config.ttl();
SetArgs args = ttl != null
? SetArgs.args().ex(ttl)
: SetArgs.args(); Defensive patterns
Strategy: validation
Validate before calling
if (ttl == null || ttl.isZero() || ttl.isNegative()) {
throw new IllegalArgumentException("TTL duration must be non-null and positive");
}
SetArgs.args().ex(ttl); Type guard
boolean isPositiveDuration(Duration d) {
return d != null && !d.isZero() && !d.isNegative();
} Try / catch
try {
args.ex(duration);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("`timeout` must not be `null`")) throw e;
args = SetArgs.args(); // skip expiry
} Prevention
- Provide defaults for optional Duration config values at mapping time
- Use @ConfigMapping with defaults instead of raw nullable Duration lookups
- Check null and sign of computed Durations before passing to Redis arg builders
When it happens
Trigger: Calling SetArgs ex(null), commonly when a Duration is read from optional configuration (e.g. ConfigProvider or Optional<Duration>) and not defaulted.
Common situations: Config property quarkus.redis-style TTL is absent, producing a null Duration; or a method parameter of type Duration is optional and the caller passes null to signal 'no expiry'.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- `timestamp` must not be `null`
- `count` must be strictly positive
- `timeout` must be positive
- `timeout` must not be `null`
- `timestamp` must not be `null`
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f935a407b2a0a100.
Report an issue: GitHub.