quarkusio/quarkus · error · IllegalArgumentException

`timestamp` must not be `null`

Error message

`timestamp` must not be `null`

What it means

GetExArgs.exAt(Instant) sets expiration as seconds since the Unix epoch, dividing timestamp.toEpochMilli() by 1000. A null Instant has no epoch value, so IllegalArgumentException is thrown eagerly. This guards the seconds-precision variant of GETEX expiration.

Source

Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/value/GetExArgs.java:64

     * Set the expiration timestamp as a number of seconds since the Unix epoch.
     *
     * @param timestamp the timestamp
     * @return the current {@code GetExArgs}
     */
    public GetExArgs exAt(long timestamp) {
        this.exAt = timestamp;
        return this;
    }

    /**
     * Set the expiration timestamp as a number of seconds since the Unix epoch.
     *
     * @param timestamp the timestamp
     * @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 expiration timeout, in milliseconds.
     *
     * @param timeout expiration timeout in milliseconds
     * @return the current {@code GetExArgs}
     */
    public GetExArgs px(long timeout) {
        this.px = timeout;
        return this;
    }

    /**
     * Set the expiration timeout, in milliseconds.

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a valid Instant, e.g. GetExArgs.INSTANCE.exAt(Instant.now().plusSeconds(60))
  2. Default the timestamp: Instant ts = expiryAt != null ? expiryAt : Instant.now().plusSeconds(60)
  3. Reject the request upstream if expiryAt is mandatory

Example fix

// before
GetExArgs args = GetExArgs.INSTANCE.exAt(expiryAt); // may be null
// after
Objects.requireNonNull(expiryAt, "expiryAt is required");
GetExArgs args = GetExArgs.INSTANCE.exAt(expiryAt);
Defensive patterns

Strategy: validation

Validate before calling

if (timestamp == null) {
    throw new IllegalArgumentException("timestamp is required before GetExArgs.exAt()");
}
GetExArgs.INSTANCE.exAt(timestamp);

Type guard

boolean hasExpiry(Instant t) { return t != null && t.isAfter(Instant.EPOCH); }

Try / catch

try {
    GetExArgs.INSTANCE.exAt(expiryAt);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Missing expiry timestamp for GETEX", e);
}

Prevention

When it happens

Trigger: Calling GetExArgs.exAt(null) — e.g. a nullable expiry Instant from a database entity, missing JSON field, or unset variable.

Common situations: Optional expiry fields on domain objects; deserialization leaving the timestamp null; scheduling code where the computed deadline was never assigned.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/6c48b74174553215. Report an issue: GitHub.