redis/redis-py · error · DataError

XCLAIM min_idle_time must be a non negative integer

Error message

XCLAIM min_idle_time must be a non negative integer

What it means

Raised by Redis.xclaim() when min_idle_time is not an int or is negative. Unlike xautoclaim, this uses a strict isinstance(int) check, so floats and numeric strings are rejected (not just negatives). bool is a subclass of int, so True/1 pass and False/0 pass as 0.

Solutions

  1. Pass an int (milliseconds) >= 0.
  2. Coerce explicitly: min_idle_time = int(float_value) if you need rounding.
  3. Reject bool if it is not semantically valid for your call.

Example fix

# before
r.xclaim('s','g','c', 1.5, ['1-0'])

# after
r.xclaim('s','g','c', 2, ['1-0'])
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(min_idle_time, int) or isinstance(min_idle_time, bool) or min_idle_time < 0:
    raise TypeError('min_idle_time must be a non-negative int')

Type guard

lambda v: isinstance(v, int) and not isinstance(v, bool) and v >= 0

Try / catch

from redis.exceptions import DataError
try:
    r.xclaim('s','g','c', ms, ids)
except DataError as e:
    log.warning('bad xclaim min_idle_time %r: %s', ms, e)

Prevention

When it happens

Trigger: Calling r.xclaim(name, group, consumer, min_idle_time, ids) with min_idle_time as a float (1.5), a string ('100'), None (fails isinstance), or a negative int (-1).

Common situations: Passing a float ms value, reading idle from config as a string, or a sign error.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:7293

        time: optional integer. This is the same as idle but instead of a
        relative amount of milliseconds, it sets the idle time to a specific
        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)))

View on GitHub (pinned to 6a6b581b48)