redis/redis-py · error · ValueError

Only one of IFEQ/IFNE/IFDEQ/IFDNE may be specified

Error message

Only one of IFEQ/IFNE/IFDEQ/IFDNE may be specified

What it means

Raised as a `ValueError` (note: not `DataError`) by `delex()` (redis/commands/core.py:2931) when more than one of `ifeq`, `ifne`, `ifdeq`, `ifdne` is non-None. DELEX (Redis 8.4+) accepts at most one conditional matcher; the client enforces that before building the command.

Solutions

  1. Pass at most one of `ifeq` / `ifne` / `ifdeq` / `ifdne`.
  2. If your config carries several, pick one with priority logic before calling.
  3. Ensure you're on Redis >= 8.4 — DELEX itself requires it.

Example fix

// before
r.delex('k', ifeq='a', ifne='b')
// after
r.delex('k', ifeq='a')  # delete only if value equals 'a'
Defensive patterns

Strategy: validation

Validate before calling

conds = {'ifeq': ifeq, 'ifne': ifne, 'ifdeq': ifdeq, 'ifdne': ifdne}
supplied = {k: v for k, v in conds.items() if v is not None}
if len(supplied) > 1:
    raise ValueError(f'delex: only one condition allowed, got {sorted(supplied)}')
r.delex('k', **supplied)

Try / catch

try:
    r.delex('k', ifeq='a')
except ValueError as e:
    # too many conditions
    ...

Prevention

When it happens

Trigger: `r.delex('k', ifeq='a', ifne='b')`, or any call combining two or more of the conditional keyword arguments.

Common situations: Building conditions from a dict via `**conds` where several keys are populated; migrating from a hypothetical 'match any' mental model; experimental API exploration (the method is marked experimental since 7.1).

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/825521623d1d4b05. Report an issue: GitHub.

Appendix: source

Thrown at redis/commands/core.py:2932

            ifeq match-valu: Optional[Union[bytes, str]] - Delete the key only if its value is equal to match-value
            ifne match-value: Optional[Union[bytes, str]] - Delete the key only if its value is not equal to match-value
            ifdeq match-digest: Optional[str] - Delete the key only if the digest of its value is equal to match-digest
            ifdne match-digest: Optional[str] - Delete the key only if the digest of its value is not equal to match-digest

        Returns:
            int: 1 if the key was deleted, 0 otherwise.
        Raises:
            redis.exceptions.ResponseError: if key exists but is not a string
                                            and a condition is specified.
            ValueError: if more than one condition is provided.


        Requires Redis 8.4 or greater.
        For more information, see https://redis.io/commands/delex
        """
        conds = [x is not None for x in (ifeq, ifne, ifdeq, ifdne)]
        if sum(conds) > 1:
            raise ValueError("Only one of IFEQ/IFNE/IFDEQ/IFDNE may be specified")

        pieces = ["DELEX", name]
        if ifeq is not None:
            pieces += ["IFEQ", ifeq]
        elif ifne is not None:
            pieces += ["IFNE", ifne]
        elif ifdeq is not None:
            pieces += ["IFDEQ", ifdeq]
        elif ifdne is not None:
            pieces += ["IFDNE", ifdne]

        return self.execute_command(*pieces)

    @overload
    def dump(self: SyncClientProtocol, name: KeyT) -> bytes | None: ...

    @overload
    def dump(self: AsyncClientProtocol, name: KeyT) -> Awaitable[bytes | None]: ...

View on GitHub (pinned to 6a6b581b48)