redis/redis-py · error · DataError

XCLAIM message_ids must be a non empty list or tuple of…

Error message

XCLAIM message_ids must be a non empty list or tuple of message IDs to claim

What it means

Raised by Redis.xclaim() when message_ids is not a list or tuple, or is an empty list/tuple. The check is `not isinstance(message_ids, (list, tuple)) or not message_ids`. A single bare ID string, a set, a generator, None, or [] all fail.

Solutions

  1. Pass a non-empty list or tuple of IDs, e.g. ['1-0', '2-0'].
  2. Guard empties: if not ids: skip the claim.
  3. Convert sets/generators to list before calling.

Example fix

# before
r.xclaim('s','g','c', 0, pending_ids)  # pending_ids == []

# after
if pending_ids:
    r.xclaim('s','g','c', 0, list(pending_ids))
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(message_ids, (list, tuple)) or len(message_ids) == 0:
    raise ValueError('message_ids must be a non-empty list/tuple')
message_ids = list(message_ids)

Type guard

lambda v: isinstance(v, (list, tuple)) and len(v) > 0

Try / catch

from redis.exceptions import DataError
try:
    r.xclaim('s','g','c', 0, ids)
except DataError as e:
    if not ids:
        pass  # nothing to claim, expected
    else:
        raise

Prevention

When it happens

Trigger: Calling r.xclaim(name, group, consumer, ms, '1-0') (string not list), r.xclaim(..., []) (empty), r.xclaim(..., {'1-0'}) (set), or passing a generator/iterator.

Common situations: Forgetting to wrap a single ID in a list, unpacking an empty result from XPENDING, or passing a set for 'deduplication'.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:7295

        Unix time (in milliseconds).

        retrycount: optional integer. set the retry counter to the specified
        value. This counter is incremented every time a message is delivered
        again.

        force: optional boolean, false by default. Creates the pending message
        entry in the PEL even if certain specified IDs are not already in the
        PEL assigned to a different client.

        justid: optional boolean, false by default. Return just an array of IDs
        of messages successfully claimed, without returning the actual message

        For more information, see https://redis.io/commands/xclaim
        """
        if not isinstance(min_idle_time, int) or min_idle_time < 0:
            raise DataError("XCLAIM min_idle_time must be a non negative integer")
        if not isinstance(message_ids, (list, tuple)) or not message_ids:
            raise DataError(
                "XCLAIM message_ids must be a non empty list or "
                "tuple of message IDs to claim"
            )

        kwargs = {}
        pieces: list[EncodableT] = [name, groupname, consumername, str(min_idle_time)]
        pieces.extend(list(message_ids))

        if idle is not None:
            if not isinstance(idle, int):
                raise DataError("XCLAIM idle must be an integer")
            pieces.extend((b"IDLE", str(idle)))
        if time is not None:
            if not isinstance(time, int):
                raise DataError("XCLAIM time must be an integer")
            pieces.extend((b"TIME", str(time)))
        if retrycount is not None:
            if not isinstance(retrycount, int):

View on GitHub (pinned to 6a6b581b48)