quarkusio/quarkus · error · IllegalArgumentException
`timestamp` must not be `null`
Error message
`timestamp` must not be `null`
What it means
GetExArgs.exAt(Instant) converts an Instant to POSIX seconds for the GETEX EXAT option; it requires a non-null Instant. Passing null would cause a downstream NPE, so the method fails fast with this IllegalArgumentException.
Source
Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/string/GetExArgs.java:67
* Sets the expiration time
*
* @param timestamp the timestamp
* @return the current {@code GetExArgs}
*/
public GetExArgs exAt(long timestamp) {
this.exAt = timestamp;
return this;
}
/**
* Sets the expiration time
*
* @param timestamp the timestamp type: posix time in seconds.
* @return the current {@code GetExArgs}
*/
public GetExArgs exAt(Instant timestamp) {
if (timestamp == null) {
throw new IllegalArgumentException("`timestamp` must not be `null`");
}
exAt(timestamp.toEpochMilli() / 1000);
return this;
}
/**
* Set the specified expire time, in milliseconds.
*
* @param timeout expire time in milliseconds.
* @return the current {@code GetExArgs}
*/
public GetExArgs px(long timeout) {
this.px = timeout;
return this;
}
/**
* Set the specified expire time, in milliseconds.View on GitHub (pinned to e1c734241f)
Solutions
- Pass a concrete non-null Instant, e.g. exAt(Instant.now().plusSeconds(3600))
- Guard with a null check and either skip exAt or use persist()/a relative ex(Duration) instead
- Use Instant.now() or a defaulted value when the source timestamp is absent
Example fix
// before
Instant expiry = null;
args.exAt(expiry);
// after
Instant expiry = computeExpiry();
if (expiry == null) {
expiry = Instant.now().plusSeconds(3600);
}
args.exAt(expiry); Defensive patterns
Strategy: validation
Validate before calling
if (timestamp == null) {
throw new IllegalArgumentException("Expiry timestamp must be provided for GETEX exAt()");
} Type guard
boolean hasExpiry(Instant i) {
return i != null && i.isAfter(Instant.now());
} Try / catch
try {
redis.string().getex(key, new GetExArgs().exAt(expiry));
} catch (IllegalArgumentException e) {
log.warn("GETEX skipped: " + e.getMessage());
} Prevention
- Ensure expiry computations never return null (use orElse with a sensible default)
- Null-check computed Instant values before calling exAt
- Validate the timestamp is in the future before sending EXAT
When it happens
Trigger: Calling GetExArgs.exAt((Instant) null) — commonly with a computed timestamp variable that is null, e.g. Instant expiry = optional.map(...).orElse(null) followed by exAt(expiry) while building getex args.
Common situations: Optional expiration timestamps from scheduling/lookup logic returning null; uninitialized fields used as the expiry; refactors where a fallback Instant was dropped.
Related errors
- `timeout` must not be `null`
- `pattern` must not be `null`
- `offset` must not be `null`
- The BitFieldType must not be `null`
- `btf` must not be `null`
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/5200f9b747ca0bcb.
Report an issue: GitHub.