redis/redis-py · error · DataError

XCLAIM retrycount must be an integer

Error message

XCLAIM retrycount must be an integer

What it means

Raised by Redis.xclaim() when the optional retrycount argument is provided and is not an int. retrycount sets the message delivery retry counter. Strict isinstance(int).

Solutions

  1. Pass an int for retrycount, or omit it.
  2. Coerce: retrycount = int(retrycount).

Example fix

# before
r.xclaim('s','g','c', 0, ['1-0'], retrycount=attempts)  # attempts is float

# after
r.xclaim('s','g','c', 0, ['1-0'], retrycount=int(attempts))
Defensive patterns

Strategy: type-guard

Validate before calling

if retrycount is not None and not isinstance(retrycount, int):
    retrycount = int(retrycount)

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling r.xclaim(..., retrycount='3') or retrycount=1.0.

Common situations: Loading retry count from JSON/config as a string or float.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:7314

                "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)))
        if retrycount is not None:
            if not isinstance(retrycount, int):
                raise DataError("XCLAIM retrycount must be an integer")
            pieces.extend((b"RETRYCOUNT", str(retrycount)))

        if force:
            if not isinstance(force, bool):
                raise DataError("XCLAIM force must be a boolean")
            pieces.append(b"FORCE")
        if justid:
            if not isinstance(justid, bool):
                raise DataError("XCLAIM justid must be a boolean")
            pieces.append(b"JUSTID")
            kwargs["parse_justid"] = True
        return self.execute_command("XCLAIM", *pieces, **kwargs)

    @overload
    def xdel(self: SyncClientProtocol, name: KeyT, *ids: StreamIdT) -> int: ...

    @overload
    def xdel(

View on GitHub (pinned to 6a6b581b48)