{"id":"24924b8a8d482a8c","repo":"redis/redis-py","slug":"xrange-count-must-be-a-positive-integer","errorCode":null,"errorMessage":"XRANGE count must be a positive integer","messagePattern":"XRANGE count must be a positive integer","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":7845,"sourceCode":"        Read stream values within an interval.\n\n        name: name of the stream.\n\n        start: first stream ID. defaults to '-',\n               meaning the earliest available.\n\n        finish: last stream ID. defaults to '+',\n                meaning the latest available.\n\n        count: if set, only return this many items, beginning with the\n               earliest available.\n\n        For more information, see https://redis.io/commands/xrange\n        \"\"\"\n        pieces = [min, max]\n        if count is not None:\n            if not isinstance(count, int) or count < 1:\n                raise DataError(\"XRANGE count must be a positive integer\")\n            pieces.append(b\"COUNT\")\n            pieces.append(str(count))\n\n        return self.execute_command(\"XRANGE\", name, *pieces, keys=[name])\n\n    @overload\n    def xread(\n        self: SyncClientProtocol,\n        streams: Dict[KeyT, StreamIdT],\n        count: int | None = None,\n        block: int | None = None,\n        max_count: int | None = None,\n        max_size: int | None = None,\n    ) -> XReadResponse: ...\n\n    @overload\n    def xread(\n        self: AsyncClientProtocol,","sourceCodeStart":7827,"sourceCodeEnd":7863,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L7827-L7863","documentation":"Raised by xrange() when the optional count argument is either not an int (isinstance check) or is less than 1. Unlike XPENDING, this uses a strict isinstance(count, int) check, so floats and numeric strings ('10', 10.0) are rejected even if their value is positive. The library enforces this because XRANGE COUNT on the server requires a positive integer.","triggerScenarios":"Call client.xrange(name, min, max, count) with count as a float (10.0), a string ('10'), zero, a negative number, or any non-int type. Booleans pass isinstance(True, int) but produce a COUNT of 1.","commonSituations":"Loading count from JSON/CSV where it arrives as a string; dividing values producing floats (e.g. n/2 when n is even); passing 0 expecting 'no limit' (use None instead).","solutions":["Pass an int >= 1, or omit count / pass None for no limit.","Coerce incoming value explicitly: count = int(count) if count else None.","Validate with isinstance(count, int) and count >= 1 before the call."],"exampleFix":"// before\nclient.xrange(\"s\", \"-\", \"+\", count=\"50\")\n// after\nclient.xrange(\"s\", \"-\", \"+\", count=50)","handlingStrategy":"validation","validationCode":"def normalize_count(v):\n    if v is None:\n        return None\n    if not isinstance(v, int) or isinstance(v, bool):\n        raise TypeError(f\"count must be int, got {type(v)}\")\n    if v < 1:\n        raise ValueError(f\"count must be >= 1, got {v}\")\n    return v\n\ncount = normalize_count(raw_count)\nclient.xrange(\"s\", \"-\", \"+\", count=count)","typeGuard":"def is_positive_int(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool) and v >= 1","tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    client.xrange(\"s\", \"-\", \"+\", count=count)\nexcept DataError as e:\n    if \"XRANGE count\" in str(e):\n        count = int(count)\n        client.xrange(\"s\", \"-\", \"+\", count=count) if count >= 1 else None\n    else:\n        raise","preventionTips":["Always coerce external count values with int() and bound-check >= 1.","Pass None rather than 0 when you want 'no limit'.","Keep stream-pagination helpers in one place so the rule is enforced once."],"tags":["redis-streams","validation","xrange","dataerror"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}