quarkusio/quarkus · error · IllegalArgumentException

`timestamp` must not be `null`

Error message

`timestamp` must not be `null`

What it means

SetArgs.exAt(Instant) sets expiration as a Unix-epoch timestamp in seconds. It rejects a null Instant with IllegalArgumentException so callers get a clear, immediate message rather than a NullPointerException from Instant.toEpochMilli().

Source

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

     * 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.
     *
     * @param timestamp the timestamp
     * @return the current {@code SetArgs}
     */
    public SetArgs 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 SetArgs}
     */
    public SetArgs px(long timeout) {
        if (timeout < 0) {
            throw new IllegalArgumentException("`timeout` must be positive");
        }
        this.px = timeout;
        return this;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the Instant is non-null before calling exAt; substitute a computed default (e.g. Instant.now().plus(ttl)) when absent.
  2. Use ex(Duration) or px(Duration) when you have a relative TTL instead of an absolute instant.
  3. Fix the upstream parsing/lookup that produced the null Instant.

Example fix

// before
SetArgs args = new SetArgs().exAt(expiresAt); // may be null
// after
SetArgs args = new SetArgs().exAt(expiresAt != null ? expiresAt : Instant.now().plusSeconds(60));
Defensive patterns

Strategy: type-guard

Validate before calling

Objects.requireNonNull(expiresAt, "expiresAt must not be null");
SetArgs args = new SetArgs().exAt(expiresAt);

Type guard

static boolean isValidInstant(Instant ts) {
    return ts != null && !ts.isBefore(Instant.now());
}

Try / catch

try {
    args = new SetArgs().exAt(expiresAt);
} catch (IllegalArgumentException e) {
    log.warn("Null expiry instant, defaulting to now+60s");
    args = new SetArgs().exAt(Instant.now().plusSeconds(60));
}

Prevention

When it happens

Trigger: Calling SetArgs.exAt(null), e.g. when the expiry Instant comes from a nullable entity field, an absent header, or a parsing failure that returned null.

Common situations: Optional expiry attributes on domain objects, JSON payloads missing the expiry field, or clock/scheduling code that failed to compute an Instant.

Related errors


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