quarkusio/quarkus · error · IllegalStateException

Cannot combine `IDLE` and `TIME`

Error message

Cannot combine `IDLE` and `TIME`

What it means

XCLAIM can set the delivery time of claimed messages either as a relative IDLE (milliseconds since now) or an absolute TIME (unix ms), but not both. XClaimArgs.toArgs() throws IllegalStateException when idle was set and time > 0 is also present, as the two are redundant/contradictory.

Source

Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/stream/XClaimArgs.java:107

     * Sets the last id of the message to claim.
     *
     * @param lastId the last id, must not be {@code null}
     * @return the current {@code XClaimArgs}
     */
    public XClaimArgs lastId(String lastId) {
        this.lastId = lastId;
        return this;
    }

    @Override
    public List<Object> toArgs() {
        List<Object> args = new ArrayList<>();

        if (idle != null) {
            args.add("IDLE");
            args.add(Long.toString(idle.toMillis()));
            if (time > 0) {
                throw new IllegalStateException("Cannot combine `IDLE` and `TIME`");
            }
        }

        if (time > 0) {
            args.add("TIME");
            args.add(Long.toString(time));
        }

        if (retryCount > 0) {
            args.add("RETRYCOUNT");
            args.add(Integer.toString(retryCount));
        }

        if (force) {
            args.add("FORCE");
        }

        if (justId) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Keep only one: use .idle(Duration) for relative delay or .time(long) for absolute timestamp
  2. Set the unused field to 0/null before building args
  3. Derive one from the other if both inputs exist (e.g. idle = time - now) and set only idle

Example fix

// before
XClaimArgs args = new XClaimArgs().idle(Duration.ofSeconds(1)).time(System.currentTimeMillis());
// after
XClaimArgs args = new XClaimArgs().idle(Duration.ofSeconds(1));
Defensive patterns

Strategy: validation

Validate before calling

if (idle != null && time > 0) throw new IllegalArgumentException("XCLAIM accepts IDLE or TIME, not both");

Try / catch

try {
    stream.xclaim(key, group, consumer, minIdle, ids, args);
} catch (IllegalStateException e) {
    // rebuild XClaimArgs with only idle or only time
}

Prevention

When it happens

Trigger: Calling xclaimArgs().idle(Duration.ofSeconds(1)) and .time(epochMs) on the same instance; or time defaulting to a positive value while idle is also set.

Common situations: Config exposing both 'idle' and 'time' options and both being applied; migrating code from TIME-based to IDLE-based claims leaving the old field set; builder reuse.

Related errors


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