quarkusio/quarkus · error · IllegalArgumentException
`timeout` must not be `null`
Error message
`timeout` must not be `null`
What it means
SetArgs.ex(Duration) converts the given Duration to seconds and delegates to ex(long). It rejects a null Duration with IllegalArgumentException up front so the failure is reported at the call site instead of as a NullPointerException deep inside duration conversion.
Source
Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/value/SetArgs.java:46
* @return the current {@code SetArgs}
*/
public SetArgs ex(long timeout) {
if (timeout <= 0) {
throw new IllegalArgumentException("`timeout` must be positive");
}
this.ex = timeout;
return this;
}
/**
* Set the expiration timeout, in seconds.
*
* @param timeout expiration timeout in seconds
* @return the current {@code SetArgs}
*/
public SetArgs ex(Duration timeout) {
if (timeout == null) {
throw new IllegalArgumentException("`timeout` must not be `null`");
}
return ex(timeout.toSeconds());
}
/**
* Set the expiration timestamp as a number of seconds since the Unix epoch.
*
* @param timestamp the timestamp
* @return the current {@code SetArgs}
*/
public SetArgs exAt(long timestamp) {
this.exAt = timestamp;
return this;
}
/**
* Set the expiration timestamp as a number of seconds since the Unix epoch.
*View on GitHub (pinned to e1c734241f)
Solutions
- Check the Duration for null before calling ex(Duration), or pass Optional/ defaulted value.
- Use a sentinel (e.g. skip the expiration args entirely) when no TTL is configured.
- If a Duration of zero was intended, note that ex(Duration.ZERO) will also throw via ex(0) — use px() for sub-second TTLs.
Example fix
// before SetArgs args = new SetArgs().ex(ttl); // ttl may be null // after SetArgs args = ttl != null ? new SetArgs().ex(ttl) : new SetArgs();
Defensive patterns
Strategy: type-guard
Validate before calling
Objects.requireNonNull(ttl, "ttl must not be null"); SetArgs args = new SetArgs().ex(ttl);
Type guard
static boolean hasTtl(Duration ttl) {
return ttl != null && !ttl.isNegative() && !ttl.isZero();
} Try / catch
try {
args = new SetArgs().ex(ttl);
} catch (IllegalArgumentException e) {
log.warn("No valid TTL configured, setting key without expiration");
args = new SetArgs();
} Prevention
- Default nullable config Durations via @ConfigMapping defaults or Optional.orElse.
- Never pass Optional.get() or possibly-null fields directly into SetArgs builders.
- Centralize SetArgs construction in one helper that validates inputs.
When it happens
Trigger: Calling SetArgs.ex((Duration) null), typically when a nullable config property or optional TTL field is passed straight through without a null check.
Common situations: Optional @ConfigMapping Duration fields defaulting to null, DB/lookup results returning no TTL, or refactorings that made a previously defaulted value nullable.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- `pattern` must not be `null`
- `timestamp` must not be `null`
- Invalid integer encoding for a bit field type: " + bit + ".
- `bits` must be strictly positive
- Signed integers support only up to 64 bits
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/94633054e3adc95a.
Report an issue: GitHub.