redis/redis-py · error · DataError

XAUTOCLAIM min_idle_time must be a nonnegative integer

Error message

XAUTOCLAIM min_idle_time must be a nonnegative integer

What it means

Raised by xautoclaim() when min_idle_time, after int() coercion, is negative. CAUTION: the guard is wrapped in try/except TypeError, so values int() cannot parse (None, lists, etc.) are SWALLOWED and forwarded to Redis - only a successfully-parsed negative trips this. This is stricter than xclaim, which uses isinstance.

Source

Thrown at redis/commands/core.py:7194

        criteria. Conceptually, equivalent to calling XPENDING and then XCLAIM,
        but provides a more straightforward way to deal with message delivery
        failures via SCAN-like semantics.
        name: name of the stream.
        groupname: name of the consumer group.
        consumername: name of a consumer that claims the message.
        min_idle_time: filter messages that were idle less than this amount of
        milliseconds.
        start_id: filter messages with equal or greater ID.
        count: optional integer, upper limit of the number of entries that the
        command attempts to claim. Set to 100 by default.
        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

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass 0 (not negative) when you want no idle filtering.
  2. Clamp upstream: min_idle_time = max(0, int(value)).
  3. Do not rely on this guard to catch non-numeric junk - validate the type yourself.

Example fix

# before
r.xautoclaim('s','g','c', min_idle_time=delta_ms)  # delta_ms < 0
# after
r.xautoclaim('s','g','c', min_idle_time=max(0, int(delta_ms)))
Defensive patterns

Strategy: validation

Validate before calling

idle = max(0, int(min_idle_time)) if min_idle_time is not None else 0
r.xautoclaim(name, group, consumer, idle)

Try / catch

from redis.exceptions import DataError
try:
    r.xautoclaim(name, group, consumer, ms)
except DataError:
    r.xautoclaim(name, group, consumer, max(0, int(ms)))

Prevention

When it happens

Trigger: xautoclaim(name, group, consumer, min_idle_time=-1) or ='-1' (int('-1') == -1). Passing min_idle_time=None or ='abc' does NOT raise here - it slips through to the server.

Common situations: Computing idle from a clock-skewed delta that went negative; using -1 as a 'no filter' sentinel; passing a float like 5.5 (int() truncates to 5, ok) - but a negative float truncates to a negative int and trips.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/e343dfd927e68ffb.json. Report an issue: GitHub.