{"id":"84962e7edbade22a","repo":"redis/redis-py","slug":"xpending-count-must-be-a-integer-0","errorCode":null,"errorMessage":"XPENDING count must be a integer >= 0","messagePattern":"XPENDING count must be a integer >= 0","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":7205,"sourceCode":"        justid: optional boolean, false by default. Return just an array of IDs\n        of messages successfully claimed, without returning the actual message\n\n        For more information, see https://redis.io/commands/xautoclaim\n        \"\"\"\n        try:\n            if int(min_idle_time) < 0:\n                raise DataError(\n                    \"XAUTOCLAIM min_idle_time must be a nonnegative integer\"\n                )\n        except TypeError:\n            pass\n\n        kwargs = {}\n        pieces = [name, groupname, consumername, min_idle_time, start_id]\n\n        try:\n            if int(count) < 0:\n                raise DataError(\"XPENDING count must be a integer >= 0\")\n            pieces.extend([b\"COUNT\", count])\n        except TypeError:\n            pass\n        if justid:\n            pieces.append(b\"JUSTID\")\n            kwargs[\"parse_justid\"] = True\n\n        return self.execute_command(\"XAUTOCLAIM\", *pieces, **kwargs)\n\n    @overload\n    def xclaim(\n        self: SyncClientProtocol,\n        name: KeyT,\n        groupname: GroupT,\n        consumername: ConsumerT,\n        min_idle_time: int,\n        message_ids: Union[List[StreamIdT], Tuple[StreamIdT]],\n        idle: int | None = None,","sourceCodeStart":7187,"sourceCodeEnd":7223,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L7187-L7223","documentation":"Raised by xautoclaim() for its `count` argument - but the MESSAGE text says 'XPENDING count', a copy-paste artifact from the sibling xpending_range code. It fires when int(count) is negative. Same try/except TypeError pattern as min_idle_time: non-coercible counts are swallowed and sent to Redis.","triggerScenarios":"xautoclaim(name, group, consumer, min_idle, count=-5) or count='-5'. count=None or count='abc' does NOT raise here. Check at core.py:7203-7208.","commonSituations":"Reusing a variable named for XPENDING; a count derived from a subtraction that underflowed; misled by the message into thinking xpending was the culprit when the failing call is xautoclaim.","solutions":["Recognize the message is misleading - audit your xautoclaim(...) count argument, not xpending.","Pass count=None (omit) or a non-negative int.","Clamp: count = None if raw is None else max(0, int(raw))."],"exampleFix":"# before\nr.xautoclaim('s','g','c', 5000, count=limit)  # limit == -1\n# after\nr.xautoclaim('s','g','c', 5000, count=max(0, int(limit)))","handlingStrategy":"validation","validationCode":"count = None if raw_count is None else max(0, int(raw_count))\nr.xautoclaim(name, group, consumer, min_idle, count=count)","typeGuard":null,"tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    r.xautoclaim(name, group, consumer, ms, count=c)\nexcept DataError as e:\n    # message says 'XPENDING' but this is xautoclaim's count\n    c = max(0, int(c)); r.xautoclaim(name, group, consumer, ms, count=c)","preventionTips":["Don't be fooled - the text 'XPENDING count' is raised inside xautoclaim.","Clamp counts to >= 0 or pass None for the default."],"tags":["redis","streams","xautoclaim","validation","range-error","misleading-message"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}