{"record":{"id":"88a445b38df89aeb","repo":"quarkusio/quarkus","slug":"cannot-use-xx-and-nx-together","errorCode":null,"errorMessage":"Cannot use XX and NX together","messagePattern":"Cannot use XX and NX together","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/sortedset/ZAddArgs.java","lineNumber":74,"sourceCode":"        this.lt = true;\n        return this;\n    }\n\n    /**\n     * Only update existing elements if the new score is greater than the current score.\n     * This flag doesn't prevent adding new elements.\n     *\n     * @return the current {@code ZAddArgs}\n     **/\n    public ZAddArgs gt() {\n        this.gt = true;\n        return this;\n    }\n\n    @Override\n    public List<Object> toArgs() {\n        if (xx && nx) {\n            throw new IllegalArgumentException(\"Cannot use XX and NX together\");\n        }\n        if (lt && gt) {\n            throw new IllegalArgumentException(\"Cannot use LT and GT together\");\n        }\n\n        List<Object> args = new ArrayList<>();\n        putFlag(args, nx, \"NX\");\n        putFlag(args, xx, \"XX\");\n        putFlag(args, lt, \"LT\");\n        putFlag(args, gt, \"GT\");\n        putFlag(args, ch, \"CH\");\n        return args;\n    }\n\n    public void putFlag(List<Object> args, boolean value, String flag) {\n        if (value) {\n            args.add(flag);\n        }","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/sortedset/ZAddArgs.java#L56-L92","documentation":"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.","triggerScenarios":"Calling zaddArgs.xx().nx() (in either order) on ZAddArgs, then passing it to a zadd/increment operation.","commonSituations":"Builder reuse: one code path sets XX, another sets NX on the same shared args object; misunderstanding flags as independent toggles.","solutions":["Remove one of the two calls: use .xx() to update-only or .nx() to add-only","Create a fresh ZAddArgs instance per operation instead of sharing/reusing one","Wrap flag-setting logic so setting one clears the other"],"exampleFix":"// before\nZAddArgs args = new ZAddArgs().xx().nx();\n// after\nZAddArgs args = new ZAddArgs().nx(); // add-only (or .xx() for update-only)","handlingStrategy":"validation","validationCode":"if (wantExistingOnly && wantNewOnly) throw new IllegalArgumentException(\"Choose XX or NX for ZADD, not both\");","typeGuard":null,"tryCatchPattern":"try {\n    sortedSet.zadd(key, score, member, args);\n} catch (IllegalArgumentException e) {\n    // recreate ZAddArgs with a single flag\n}","preventionTips":["Use a fresh ZAddArgs per operation; never share builders","Represent XX/NX as one enum (UpdatePolicy.EXISTING | NEW) rather than two booleans","Add unit tests asserting the toArgs() output for each flag combo"],"tags":["redis","sorted-set","mutually-exclusive-options","zadd"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}