redis/redis-py · error · DataError
``enx`` requires one of ``ex``, ``px``, ``exat``, or ``pxat`
Error message
``enx`` requires one of ``ex``, ``px``, ``exat``, or ``pxat``.
What it means
increx() supports enx (set expiration only when the key does not already have one), but enx is meaningless without an actual expiry value to set. The guard at core.py:3500 raises DataError when enx=True is passed without any of ex/px/exat/pxat.
Source
Thrown at redis/commands/core.py:3501
):
raise DataError("``byfloat`` and ``byint`` are mutually exclusive.")
if not at_most_one_value_set(
(
ex is not None,
px is not None,
exat is not None,
pxat is not None,
persist,
)
):
raise DataError(
"``ex``, ``px``, ``exat``, ``pxat``, "
"and ``persist`` are mutually exclusive."
)
if enx and ex is None and px is None and exat is None and pxat is None:
raise DataError(
"``enx`` requires one of ``ex``, ``px``, ``exat``, or ``pxat``."
)
pieces: list[EncodableT] = [name]
if byfloat is not None:
pieces.extend(("BYFLOAT", byfloat))
elif byint is not None:
pieces.extend(("BYINT", byint))
if lbound is not None:
pieces.extend(("LBOUND", lbound))
if ubound is not None:
pieces.extend(("UBOUND", ubound))
if saturate:
pieces.append("SATURATE")
pieces.extend(extract_expire_flags(ex, px, exat, pxat))View on GitHub (pinned to da03cdc7e8)
Solutions
- Pair enx with exactly one expiry option, e.g. r.increx('k', byint=1, ex=60, enx=True).
- If you only want to preserve an existing TTL, simply omit all expiry options (enx not needed).
- When building kwargs dynamically, only set enx when an expiry option is also present.
Example fix
# before
r.increx('k', byint=1, enx=True)
# after
r.increx('k', byint=1, ex=60, enx=True) Defensive patterns
Strategy: validation
Validate before calling
if enx and ex is None and px is None and exat is None and pxat is None:
raise ValueError('increx: enx requires an expiry option (ex/px/exat/pxat)')
r.increx('k', byint=1, ex=ex, enx=enx) Type guard
def valid_enx_usage(enx, ex, px, exat, pxat) -> bool:
return not enx or any(x is not None for x in (ex, px, exat, pxat)) Try / catch
from redis.exceptions import DataError
try:
r.increx('k', byint=1, enx=True)
except DataError as e:
if 'enx requires' in str(e):
r.increx('k', byint=1, ex=60, enx=True)
else:
raise Prevention
- Only set enx when you are also setting an expiry option.
- If you just want to preserve existing TTL, omit all expiry args entirely.
When it happens
Trigger: r.increx('k', byint=1, enx=True) with no expiry option. persist is not a valid companion for enx either.
Common situations: Forwarding enx from config without also forwarding the chosen expiry; misunderstanding enx as a standalone 'keep existing TTL' (that is the default behavior when no expiry is passed).
Related errors
- ``byfloat`` and ``byint`` are mutually exclusive.
- Only one of IFEQ/IFNE/IFDEQ/IFDNE may be specified
- ``ex``, ``px``, ``exat``, ``pxat``, and ``persist`` are mutu
- ``ex``, ``px``, ``exat``, ``pxat``, and ``keepttl`` are mutu
- Both start and end must be specified
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/0962d7bb66047d24.json.
Report an issue: GitHub.