redis/redis-py · error · DataError

XPENDING idle must be a integer >= 0

Error message

XPENDING idle must be a integer >= 0

What it means

Raised by Redis.xpending_range() when idle is int-coercible and int(idle) < 0. Like xautoclaim, the check sits in try/except TypeError, so a non-coercible idle is silently skipped (the IDLE option is then NOT emitted). Only a negative coerced value raises.

Solutions

  1. Pass a non-negative int (ms) for idle, or omit it.
  2. Clamp: idle = max(0, int(idle)).

Example fix

# before
r.xpending_range('s','g','-','+',10, idle=threshold)  # threshold = -1

# after
r.xpending_range('s','g','-','+',10, idle=max(0, int(threshold)))
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

from redis.exceptions import DataError
try:
    r.xpending_range('s','g','-','+',10, idle=i)
except DataError as e:
    log.warning('bad xpending idle %r: %s', i, e)

Prevention

When it happens

Trigger: Calling r.xpending_range('s','g','-','+',10, idle=-1) or idle='-5'. A non-coercible idle (e.g. idle='abc') is swallowed and omitted rather than raising.

Common situations: Sign error in an idle threshold computed from timestamps.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:7784

        if {min, max, count} == {None}:
            if idle is not None or consumername is not None:
                raise DataError(
                    "if XPENDING is provided with idle time"
                    " or consumername, it must be provided"
                    " with min, max and count parameters"
                )
            return self.xpending(name, groupname)

        pieces = [name, groupname]
        if min is None or max is None or count is None:
            raise DataError(
                "XPENDING must be provided with min, max "
                "and count parameters, or none of them."
            )
        # idle
        try:
            if int(idle) < 0:
                raise DataError("XPENDING idle must be a integer >= 0")
            pieces.extend(["IDLE", idle])
        except TypeError:
            pass
        # count
        try:
            if int(count) < 0:
                raise DataError("XPENDING count must be a integer >= 0")
            pieces.extend([min, max, count])
        except TypeError:
            pass
        # consumername
        if consumername:
            pieces.append(consumername)

        return self.execute_command("XPENDING", *pieces, parse_detail=True)

    @overload
    def xrange(

View on GitHub (pinned to 6a6b581b48)