quarkusio/quarkus · error · IllegalArgumentException

`timeout` must be positive

Error message

`timeout` must be positive

What it means

SetArgs.ex(long) sets the EX (seconds) option for a Redis SET command; the client requires a strictly positive value. Redis itself rejects non-positive expire times, so the Quarkus Redis client fails fast with IllegalArgumentException. Zero and negative values are both invalid.

Source

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

    private long ex = -1;
    private long exAt = -1;
    private long px = -1;
    private long pxAt = -1;
    private boolean nx;
    private boolean keepttl;
    private boolean xx;
    private boolean get;

    /**
     * Set the specified expire time, in seconds.
     *
     * @param timeout expire time in seconds.
     * @return the current {@code GetExArgs}
     */
    public SetArgs ex(long timeout) {
        if (timeout <= 0) {
            throw new IllegalArgumentException("`timeout` must be positive");
        }
        this.ex = timeout;
        return this;
    }

    /**
     * Sets the expiration.
     *
     * @param timeout expire time in seconds.
     * @return the current {@code GetExArgs}
     */
    public SetArgs ex(Duration timeout) {
        if (timeout == null) {
            throw new IllegalArgumentException("`timeout` must not be `null`");
        }
        return ex(timeout.toMillis() / 1000);
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a value >= 1 second; clamp with Math.max(1, timeoutSeconds) if a minimum TTL is acceptable
  2. Only call ex() when the timeout is > 0: build args conditionally
  3. Fix the source of the value: validate configuration so a TTL of 0 means 'skip ex()' rather than reaching the setter

Example fix

// before
SetArgs args = SetArgs.args().ex(ttlSeconds); // throws when ttlSeconds <= 0

// after
SetArgs args = ttlSeconds > 0
    ? SetArgs.args().ex(ttlSeconds)
    : SetArgs.args();
Defensive patterns

Strategy: validation

Validate before calling

if (ttlSeconds <= 0) {
    throw new IllegalArgumentException("TTL must be positive, got: " + ttlSeconds);
}
SetArgs.args().ex(ttlSeconds);

Try / catch

try {
    args.ex(timeout);
} catch (IllegalArgumentException e) {
    if (!e.getMessage().contains("`timeout` must be positive")) throw e;
    args = SetArgs.args(); // proceed without expiry
}

Prevention

When it happens

Trigger: Calling SetArgs.ex(0) or ex(-n), usually from a timeout variable initialized to 0 or computed as a negative difference of timestamps.

Common situations: A configured TTL defaults to 0 meaning 'no expiry', but the code calls ex(0) unconditionally instead of skipping ex(); or a subtraction like (deadline - now) yields 0 or negative when the deadline already passed.

Understand the failure class

Related errors


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