{"id":"4bbcce1d1f41adde","repo":"redis/redis-py","slug":"nx-xx-ifeq-ifne-ifdeq-i","errorCode":null,"errorMessage":"``nx``, ``xx``, ``ifeq``, ``ifne``, ``ifdeq``, ``ifdne`` are mutually exclusive.","messagePattern":"``nx``, ``xx``, ``ifeq``, ``ifne``, ``ifdeq``, ``ifdne`` are mutually exclusive\\.","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":4427,"sourceCode":"            )\n        ):\n            raise DataError(\n                \"``ex``, ``px``, ``exat``, ``pxat``, \"\n                \"and ``keepttl`` are mutually exclusive.\"\n            )\n\n        # Enforce mutual exclusivity among all conditional switches.\n        if not at_most_one_value_set(\n            (\n                nx,\n                xx,\n                ifeq is not None,\n                ifne is not None,\n                ifdeq is not None,\n                ifdne is not None,\n            )\n        ):\n            raise DataError(\n                \"``nx``, ``xx``, ``ifeq``, ``ifne``, ``ifdeq``, ``ifdne`` are mutually exclusive.\"\n            )\n\n        pieces: list[EncodableT] = [name, value]\n        options = {}\n\n        # Conditional modifier (exactly one at most)\n        if nx:\n            pieces.append(\"NX\")\n        elif xx:\n            pieces.append(\"XX\")\n        elif ifeq is not None:\n            pieces.extend((\"IFEQ\", ifeq))\n        elif ifne is not None:\n            pieces.extend((\"IFNE\", ifne))\n        elif ifdeq is not None:\n            pieces.extend((\"IFDEQ\", ifdeq))\n        elif ifdne is not None:","sourceCodeStart":4409,"sourceCodeEnd":4445,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L4409-L4445","documentation":"Raised by Redis.set() when more than one conditional-write switch is active. nx (set if not exists), xx (set if exists), ifeq (set if value matches digest), ifne (set if value differs), ifdeq, and ifdne are mutually exclusive because they all map to a single conditional clause in the Redis SET command. The client enforces this with at_most_one_value_set before issuing the command.","triggerScenarios":"Calling client.set(key, val, nx=True, xx=True), or client.set(key, val, nx=True, ifeq=digest), i.e. enabling two or more of the nx/xx/ifeq/ifne/ifdeq/ifdne flags simultaneously.","commonSituations":"Code that toggles nx/xx conditionally but defaults both to a truthy value; merging two code paths where one sets nx and another sets xx; using ifeq/ifne (experimental_args, Redis 8.4+) alongside the older nx/xx flags.","solutions":["Choose exactly one conditional modifier per set() call.","Make nx/xx mutually exclusive in your caller logic (e.g. an enum or a single mode variable) rather than passing independent booleans.","If you need compare-and-set semantics, use ifeq/ifne alone (requires Redis 8.4+) and do not combine with nx/xx."],"exampleFix":"# before\nawait r.set(\"k\", \"v\", nx=True, xx=True)\n# after\nawait r.set(\"k\", \"v\", nx=True)","handlingStrategy":"validation","validationCode":"VALID_CONDITIONAL = {'nx', 'xx', 'ifeq', 'ifne', 'ifdeq', 'ifdne'}\ndef _at_most_one_conditional(nx, xx, ifeq, ifne, ifdeq, ifdne):\n    active = [k for k, v in (('nx', nx), ('xx', xx), ('ifeq', ifeq), ('ifne', ifne), ('ifdeq', ifdeq), ('ifdne', ifdne)) if v not in (None, False)]\n    if len(active) > 1:\n        raise ValueError(f'Only one conditional allowed, got: {active}')\n    return active[0] if active else None","typeGuard":null,"tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    await r.set('k', 'v', nx=True)\nexcept DataError as e:\n    if 'mutually exclusive' in str(e):\n        await r.set('k', 'v', nx=True)  # retry with single mode","preventionTips":["Model the conditional mode as an enum and derive the boolean flags from it.","Default nx/xx to False and only set the one you intend.","Remember ifeq/ifne/ifdeq/ifdne are experimental and require Redis 8.4+."],"tags":["set","conditional","validation","dataerror"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}