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 xclaim() when min_idle_time is not an int or is negative. Unlike xautoclaim, this uses a STRICT isinstance(int) test (core.py:7292), so floats and strings are rejected here; bool passes because bool subclasses int.

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 da03cdc7e8)

Solutions

  1. Pass a Python int >= 0.
  2. Coerce: min_idle_time = int(max(0, value)) - but only if you know the value is numeric.
  3. Watch for numpy/pandas scalar types - cast with int().

Example fix

# before
r.xclaim('s','g','c', 5.5, ['1-0'])  # float -> fails
# after
r.xclaim('s','g','c', int(5.5), ['1-0'])
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(min_idle_time, int) and min_idle_time >= 0, 'min_idle_time must be int >= 0'
r.xclaim(name, group, consumer, min_idle_time, ids)

Type guard

def is_nonneg_int(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v >= 0

Try / catch

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

Prevention

When it happens

Trigger: xclaim(..., min_idle_time=5.0) (float), ='5' (str), =-1. bool like True is accepted as 1.

Common situations: Carrying a float milliseconds value through; reading a string from config; passing a numpy int (not a Python int).

Related errors


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