{"record":{"id":"98709eff0fc0ba83","repo":"redis/redis-py","slug":"xdelex-requires-at-least-one-message-id","errorCode":null,"errorMessage":"XDELEX requires at least one message ID","messagePattern":"XDELEX requires at least one message ID","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":7375,"sourceCode":"    def xdelex(\n        self: AsyncClientProtocol,\n        name: KeyT,\n        *ids: StreamIdT,\n        ref_policy: Literal[\"KEEPREF\", \"DELREF\", \"ACKED\"] = \"KEEPREF\",\n    ) -> Awaitable[int]: ...\n\n    def xdelex(\n        self,\n        name: KeyT,\n        *ids: StreamIdT,\n        ref_policy: Literal[\"KEEPREF\", \"DELREF\", \"ACKED\"] = \"KEEPREF\",\n    ) -> int | Awaitable[int]:\n        \"\"\"\n        Extended version of XDEL that provides more control over how message entries\n        are deleted concerning consumer groups.\n        \"\"\"\n        if not ids:\n            raise DataError(\"XDELEX requires at least one message ID\")\n\n        if ref_policy not in {\"KEEPREF\", \"DELREF\", \"ACKED\"}:\n            raise DataError(\"XDELEX ref_policy must be one of: KEEPREF, DELREF, ACKED\")\n\n        pieces = [name, ref_policy, \"IDS\", len(ids)]\n        pieces.extend(ids)\n        return self.execute_command(\"XDELEX\", *pieces)\n\n    @overload\n    def xgroup_create(\n        self: SyncClientProtocol,\n        name: KeyT,\n        groupname: GroupT,\n        id: StreamIdT = \"$\",\n        mkstream: bool = False,\n        entries_read: int | None = None,\n    ) -> bool: ...\n","sourceCodeStart":7357,"sourceCodeEnd":7393,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L7357-L7393","documentation":"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:`.","triggerScenarios":"Calling r.xdelex('mystream') with no IDs, or r.xdelex('mystream', *[]) where the list unpacks to nothing.","commonSituations":"Unpacking an empty list of IDs computed from a filter that matched nothing, or forgetting the IDs entirely.","solutions":["Supply at least one ID, e.g. r.xdelex('mystream', '1-0', ref_policy='KEEPREF').","Short-circuit when the ID list is empty instead of calling xdelex."],"exampleFix":"# before\nids = []\nr.xdelex('mystream', *ids)  # raises\n\n# after\nif ids:\n    r.xdelex('mystream', *ids, ref_policy='KEEPREF')","handlingStrategy":"validation","validationCode":"if not ids:\n    raise ValueError('xdelex requires at least one id')","typeGuard":"lambda *ids: len(ids) > 0","tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    r.xdelex('mystream', *ids)\nexcept DataError as e:\n    if ids:\n        raise\n    # empty id set is a no-op","preventionTips":["Guard against empty ID lists before calling xdelex; it is never meaningful to delete nothing."],"tags":["stream","xdelex","validation","argument-shape"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}