quarkusio/quarkus · error · IllegalArgumentException

`timeout` must be positive

Error message

`timeout` must be positive

What it means

SetArgs.ex(long) sets the EXPIRE (seconds) option for Redis SET commands. The Quarkus Redis datasource validates arguments eagerly and throws IllegalArgumentException when timeout <= 0, since a non-positive expiration is meaningless to Redis and almost always indicates a caller bug (e.g. a zeroed or miscomputed value).

Source

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

    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 expiration timeout, in seconds.
     *
     * @param timeout expiration timeout in seconds
     * @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());
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the timeout passed to ex(long) is >= 1 second before building the SetArgs.
  2. If the intended TTL is sub-second, use px(Duration) / px(long) instead (milliseconds).
  3. Check the config value or computation feeding the TTL; guard against 0/negative defaults.

Example fix

// before
SetArgs args = new SetArgs().ex(ttlMillis / 1000); // 500ms -> 0 -> throws
// after
SetArgs args = new SetArgs().px(Duration.ofMillis(ttlMillis));
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

static boolean isValidExTimeout(long timeout) {
    return timeout > 0;
}

Try / catch

try {
    args = new SetArgs().ex(ttlSeconds);
} catch (IllegalArgumentException e) {
    log.warn("Invalid SET expiration " + ttlSeconds + ", defaulting to 60s");
    args = new SetArgs().ex(60);
}

Prevention

When it happens

Trigger: Calling SetArgs.ex(0), SetArgs.ex(-1), or any ex(long) with a value <= 0, directly or via any value API that accepts SetArgs (e.g. RedisValueCommands.set(key, value, args)).

Common situations: Passing a computed TTL that evaluates to 0 because of unit-conversion mistakes (e.g. ms-to-seconds truncation of sub-second values), uninitialized config defaults of 0, or misreading the parameter as milliseconds.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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