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 Redis.xdelex() when no message IDs are supplied via *ids. xdelex is the extended XDEL with reference-policy control; it requires at least one ID. The check is `if not ids:`.

Solutions

  1. Supply at least one ID, e.g. r.xdelex('mystream', '1-0', ref_policy='KEEPREF').
  2. Short-circuit when the ID list is empty instead of calling xdelex.

Example fix

# before
ids = []
r.xdelex('mystream', *ids)  # raises

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

Strategy: validation

Validate before calling

if not ids:
    raise ValueError('xdelex requires at least one id')

Type guard

lambda *ids: len(ids) > 0

Try / catch

from redis.exceptions import DataError
try:
    r.xdelex('mystream', *ids)
except DataError as e:
    if ids:
        raise
    # empty id set is a no-op

Prevention

When it happens

Trigger: Calling r.xdelex('mystream') with no IDs, or r.xdelex('mystream', *[]) where the list unpacks to nothing.

Common situations: Unpacking an empty list of IDs computed from a filter that matched nothing, or forgetting the IDs entirely.

Related errors


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

Appendix: 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 6a6b581b48)