{"record":{"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/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L4409-L4445","documentation":"Raised by set() when more than one of the conditional switches (nx, xx, ifeq, ifne, ifdeq, ifdne) is supplied at the same time. These flags all control the SET-conditional behavior and Redis itself only allows one, so the client validates this up front via at_most_one_value_set() before building the command. It is a DataError (subclass of RedisError).","triggerScenarios":"Calling client.set('k', 'v', nx=True, xx=True), or client.set('k', 'v', nx=True, ifeq='old'), or any combination where two or more of nx/xx/ifeq/ifne/ifdeq/ifdne are truthy or non-None simultaneously. Passing a list of conditional kwargs through **kwargs into set() can also trigger it unintentionally.","commonSituations":"Refactoring an NX-based lock to use IFEQ compare-and-swap but forgetting to remove nx=True. Building SET options dynamically from a dict and accidentally including two conditionals. Copy-pasting a set() call that already had xx=True and appending ifne for a new feature.","solutions":["Inspect the set() call and keep only one conditional argument (nx, xx, ifeq, ifne, ifdeq, or ifdne).","If you are building options dynamically, filter the conditional keys so at most one survives before calling set().","For compare-and-swap use ifeq/ifne instead of combining nx/xx with a value comparison."],"exampleFix":"# before\nawait client.set('k', 'v', nx=True, ifeq='expected')\n\n# after\nawait client.set('k', 'v', ifeq='expected')","handlingStrategy":"validation","validationCode":"CONDITIONAL_KWARGS = {'nx', 'xx', 'ifeq', 'ifne', 'ifdeq', 'ifdne'}\nprovided = {\n    k: v for k, v in {\n        'nx': nx, 'xx': xx,\n        'ifeq': ifeq, 'ifne': ifne,\n        'ifdeq': ifdeq, 'ifdne': ifdne,\n    }.items()\n    if (v is not None and v is not False)\n}\nif len(provided) > 1:\n    raise ValueError(f'Only one conditional allowed, got: {list(provided)}')\nawait client.set('k', 'v', **provided)","typeGuard":null,"tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    await client.set('k', 'v', nx=True, ifeq='x')\nexcept DataError as e:\n    if 'mutually exclusive' in str(e):\n        # pick a single conditional and retry\n        await client.set('k', 'v', ifeq='x')","preventionTips":["Keep SET conditional flags in a single variable and pass it through, never hardcode two.","When refactoring from nx/xx to ifeq/ifne, grep for the old flag and remove it.","Build the conditional kwargs dict dynamically and assert len <= 1 before calling set()."],"tags":["set","conditional-flags","mutual-exclusivity","validation"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}