{"record":{"id":"5676bf36fbc0698f","repo":"redis/redis-py","slug":"ex-px-exat-pxat-and-persist","errorCode":null,"errorMessage":"``ex``, ``px``, ``exat``, ``pxat``, and ``persist`` are mutually exclusive.","messagePattern":"``ex``, ``px``, ``exat``, ``pxat``, and ``persist`` are mutually exclusive\\.","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":3283,"sourceCode":"        specified in unix time.\n\n        ``pxat`` sets an expire flag on key ``name`` for ``ex`` milliseconds,\n        specified in unix time.\n\n        ``persist`` remove the time to live associated with ``name``.\n\n        For more information, see https://redis.io/commands/getex\n        \"\"\"\n        if not at_most_one_value_set(\n            (\n                ex is not None,\n                px is not None,\n                exat is not None,\n                pxat is not None,\n                persist,\n            )\n        ):\n            raise DataError(\n                \"``ex``, ``px``, ``exat``, ``pxat``, \"\n                \"and ``persist`` are mutually exclusive.\"\n            )\n\n        exp_options: list[EncodableT] = extract_expire_flags(ex, px, exat, pxat)\n\n        if persist:\n            exp_options.append(\"PERSIST\")\n\n        return self.execute_command(\"GETEX\", name, *exp_options)\n\n    def __getitem__(self, name: KeyT):\n        \"\"\"\n        Return the value at key ``name``, raises a KeyError if the key\n        doesn't exist.\n        \"\"\"\n        value = self.get(name)\n        if value is not None:","sourceCodeStart":3265,"sourceCodeEnd":3301,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L3265-L3301","documentation":"Raised as a `DataError` by `getex()` (redis/commands/core.py:3274) via `at_most_one_value_set(...)` when more than one of `ex`, `px`, `exat`, `pxat`, or `persist` is set. GETEX sets exactly one expiration policy (or PERSIST to remove TTL); combining them is ambiguous and rejected client-side.","triggerScenarios":"`r.getex('k', ex=10, px=1000)`, `r.getex('k', ex=10, persist=True)`, or any call where two or more of those expiry kwargs are non-None/non-False.","commonSituations":"Generic 'set expiry' helper that forwards a dict of kwargs and accidentally overlaps; refactoring code that previously set TTL separately; defaults that collide with explicit args.","solutions":["Choose exactly one expiration form (seconds via `ex`, ms via `px`, absolute seconds via `exat`, absolute ms via `pxat`, or `persist=True`).","Build the expiry choice through a single resolved variable rather than passing multiple.","Validate with `at_most_one_value_set` yourself if you wrap the call."],"exampleFix":"// before\nr.getex('k', ex=10, px=1000)\n// after\nr.getex('k', ex=10)  # 10-second TTL","handlingStrategy":"validation","validationCode":"exp_args = [ex, px, exat, pxat]\nset_exp = [a for a in exp_args if a is not None]\nif len(set_exp) + (1 if persist else 0) > 1:\n    raise ValueError('getex: at most one expiry option allowed')\nr.getex('k', **({} if not set_exp else {'ex': set_exp[0]}))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reuse the library's own at_most_one_value_set helper in wrappers.","Represent TTL as one canonical field plus a unit enum."],"tags":["getex","arguments","validation","expiry","dataerror"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}