redis/redis-py · error · DataError

XDELEX requires at least one message ID

Error message

XDELEX requires at least one message ID

What it means

Raised by xdelex() when no message id is supplied. XDELEX needs at least one id to delete. Check at core.py:7374: `if not ids` on the *ids vararg.

Source

Thrown at redis/commands/core.py:7375

    def xdelex(
        self: AsyncClientProtocol,
        name: KeyT,
        *ids: StreamIdT,
        ref_policy: Literal["KEEPREF", "DELREF", "ACKED"] = "KEEPREF",
    ) -> Awaitable[int]: ...

    def xdelex(
        self,
        name: KeyT,
        *ids: StreamIdT,
        ref_policy: Literal["KEEPREF", "DELREF", "ACKED"] = "KEEPREF",
    ) -> int | Awaitable[int]:
        """
        Extended version of XDEL that provides more control over how message entries
        are deleted concerning consumer groups.
        """
        if not ids:
            raise DataError("XDELEX requires at least one message ID")

        if ref_policy not in {"KEEPREF", "DELREF", "ACKED"}:
            raise DataError("XDELEX ref_policy must be one of: KEEPREF, DELREF, ACKED")

        pieces = [name, ref_policy, "IDS", len(ids)]
        pieces.extend(ids)
        return self.execute_command("XDELEX", *pieces)

    @overload
    def xgroup_create(
        self: SyncClientProtocol,
        name: KeyT,
        groupname: GroupT,
        id: StreamIdT = "$",
        mkstream: bool = False,
        entries_read: int | None = None,
    ) -> bool: ...

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass at least one id: r.xdelex(name, id1, id2, ...).
  2. Guard: if ids: r.xdelex(name, *ids) - XDELEX on zero ids is a no-op anyway.
  3. Remember ref_policy is keyword-only-ish (after *ids) - ids come first.

Example fix

# before
r.xdelex('s')  # no ids
# after
if ids:
    r.xdelex('s', *ids, ref_policy='KEEPREF')
Defensive patterns

Strategy: validation

Validate before calling

if not ids:
    raise ValueError('xdelex needs >= 1 id')
r.xdelex(name, *ids, ref_policy=ref_policy)

Try / catch

from redis.exceptions import DataError
try:
    r.xdelex(name, *ids)
except DataError:
    pass  # nothing to delete

Prevention

When it happens

Trigger: r.xdelex('mystream') with no positional ids, or r.xdelex('mystream', ref_policy='KEEPREF') only.

Common situations: Building the id list from a filter that returned empty and still calling; refactoring from xdel and forgetting ids; spreading an empty tuple.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/98709eff0fc0ba83.json. Report an issue: GitHub.