redis/redis-py · error · DataError

XPENDING count must be a integer >= 0

Error message

XPENDING count must be a integer >= 0

What it means

Raised inside Redis.xautoclaim() for its count argument when int(count) < 0. IMPORTANT: the message text says 'XPENDING count' but the code at core.py:7205 lives in xautoclaim() -- the string was copied from the XPENDING path and is misleading. count limits how many entries XAUTOCLAIM tries to claim. The check uses try/except TypeError, so non-coercible counts are silently skipped (and not sent); only a negative coerced count raises.

Solutions

  1. Pass a non-negative int for count (or omit it to use the server default).
  2. Compute defensively: count = max(0, int(count)).
  3. Note the misleading 'XPENDING' text in the error; the failing call is xautoclaim.

Example fix

# before
r.xautoclaim('s', 'g', 'c', 0, '0-0', count=limit - offset)  # negative

# after
count = max(0, limit - offset)
r.xautoclaim('s', 'g', 'c', 0, '0-0', count=count)
Defensive patterns

Strategy: validation

Validate before calling

if count is not None:
    count = int(count)
    if count < 0:
        raise ValueError('xautoclaim count must be >= 0')

Type guard

lambda c: c is None or (isinstance(c, int) and not isinstance(c, bool) and c >= 0)

Try / catch

from redis.exceptions import DataError
try:
    r.xautoclaim('s','g','c',0,'0-0', count=n)
except DataError as e:
    # remember: message says 'XPENDING' but the call is xautoclaim
    log.warning('bad xautoclaim count %r: %s', n, e)

Prevention

When it happens

Trigger: Calling r.xautoclaim(name, group, consumer, min_idle_time, start, count=-1) or count='-3'. A count like 'abc' is swallowed by TypeError and omitted from the command rather than raising.

Common situations: Reusing a page-size variable that underflows to -1, or computing count = limit - offset where offset exceeds limit.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:7205

        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/xautoclaim
        """
        try:
            if int(min_idle_time) < 0:
                raise DataError(
                    "XAUTOCLAIM min_idle_time must be a nonnegative integer"
                )
        except TypeError:
            pass

        kwargs = {}
        pieces = [name, groupname, consumername, min_idle_time, start_id]

        try:
            if int(count) < 0:
                raise DataError("XPENDING count must be a integer >= 0")
            pieces.extend([b"COUNT", count])
        except TypeError:
            pass
        if justid:
            pieces.append(b"JUSTID")
            kwargs["parse_justid"] = True

        return self.execute_command("XAUTOCLAIM", *pieces, **kwargs)

    @overload
    def xclaim(
        self: SyncClientProtocol,
        name: KeyT,
        groupname: GroupT,
        consumername: ConsumerT,
        min_idle_time: int,
        message_ids: Union[List[StreamIdT], Tuple[StreamIdT]],
        idle: int | None = None,

View on GitHub (pinned to 6a6b581b48)