redis/redis-py · error · DataError
XCLAIM message_ids must be a non empty list or tuple of mess
Error message
XCLAIM message_ids must be a non empty list or tuple of message IDs to claim
What it means
Raised by xclaim() when message_ids is not a list/tuple, or is empty. Strict check at core.py:7294: `not isinstance(message_ids, (list, tuple)) or not message_ids`. A single id string, a set, a generator, or None all fail.
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 da03cdc7e8)
Solutions
- Pass a non-empty list or tuple of id strings.
- Skip the XCLAIM call when you have no ids: if not ids: return [].
- Materialize generators: list(gen) before passing.
Example fix
# before
r.xclaim('s','g','c', 1000, pending_ids) # pending_ids == []
# after
if pending_ids:
r.xclaim('s','g','c', 1000, list(pending_ids)) Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(message_ids, (list, tuple)) or not message_ids:
raise ValueError('message_ids must be a non-empty list/tuple')
r.xclaim(name, group, consumer, ms, message_ids) Type guard
def is_id_list(v) -> bool:
return isinstance(v, (list, tuple)) and len(v) > 0 Try / catch
from redis.exceptions import DataError
try:
r.xclaim(name, group, consumer, ms, ids)
except DataError:
ids = list(ids) if ids else []
if ids: r.xclaim(name, group, consumer, ms, ids) Prevention
- Short-circuit: skip XCLAIM when the pending set is empty.
- Always pass list(...)/tuple(...) - never bare strings, sets, or generators.
When it happens
Trigger: xclaim(..., message_ids=[]), =None, ='1-0' (bare string), =set(), =gen(). Spreading an empty list: message_ids=[] still fails the truthiness test.
Common situations: Building ids from a filter that returned nothing and still calling XCLAIM; passing a comma-separated string instead of a list; passing a generator expression; unpacking a variable that happened to be empty.
Related errors
- XCLAIM min_idle_time must be a non negative integer
- XCLAIM idle must be an integer
- XCLAIM time must be an integer
- XCLAIM retrycount must be an integer
- XCLAIM force must be a boolean
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/59d13e4e455f7e12.json.
Report an issue: GitHub.