quarkusio/quarkus · error · IllegalArgumentException

Cannot use XX and NX together

Error message

Cannot use XX and NX together

What it means

ZADD supports the XX (only update existing) and NX (only add new) modifiers, but they are semantically contradictory: an element cannot be both already present and absent. The library detects both flags set in ZAddArgs.toArgs() and throws before the command is sent.

Source

Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/sortedset/ZAddArgs.java:74

        this.lt = true;
        return this;
    }

    /**
     * Only update existing elements if the new score is greater than the current score.
     * This flag doesn't prevent adding new elements.
     *
     * @return the current {@code ZAddArgs}
     **/
    public ZAddArgs gt() {
        this.gt = true;
        return this;
    }

    @Override
    public List<Object> toArgs() {
        if (xx && nx) {
            throw new IllegalArgumentException("Cannot use XX and NX together");
        }
        if (lt && gt) {
            throw new IllegalArgumentException("Cannot use LT and GT together");
        }

        List<Object> args = new ArrayList<>();
        putFlag(args, nx, "NX");
        putFlag(args, xx, "XX");
        putFlag(args, lt, "LT");
        putFlag(args, gt, "GT");
        putFlag(args, ch, "CH");
        return args;
    }

    public void putFlag(List<Object> args, boolean value, String flag) {
        if (value) {
            args.add(flag);
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove one of the two calls: use .xx() to update-only or .nx() to add-only
  2. Create a fresh ZAddArgs instance per operation instead of sharing/reusing one
  3. Wrap flag-setting logic so setting one clears the other

Example fix

// before
ZAddArgs args = new ZAddArgs().xx().nx();
// after
ZAddArgs args = new ZAddArgs().nx(); // add-only (or .xx() for update-only)
Defensive patterns

Strategy: validation

Validate before calling

if (wantExistingOnly && wantNewOnly) throw new IllegalArgumentException("Choose XX or NX for ZADD, not both");

Try / catch

try {
    sortedSet.zadd(key, score, member, args);
} catch (IllegalArgumentException e) {
    // recreate ZAddArgs with a single flag
}

Prevention

When it happens

Trigger: Calling zaddArgs.xx().nx() (in either order) on ZAddArgs, then passing it to a zadd/increment operation.

Common situations: Builder reuse: one code path sets XX, another sets NX on the same shared args object; misunderstanding flags as independent toggles.

Related errors


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