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

  1. Check the Duration for null before calling ex(Duration), or pass Optional/ defaulted value.
  2. Use a sentinel (e.g. skip the expiration args entirely) when no TTL is configured.
  3. 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

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

Related errors


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