{"record":{"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/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L7827-L7863","documentation":"Raised by RedisClient xrange() (redis/commands/core.py:7845) as a DataError when the count argument is present but is not a Python int or is less than 1. The library validates client-side before sending the XRANGE command so an invalid COUNT never reaches the server. Note bool is a subclass of int so True/False slip through; floats, strings, and zero/negative ints are rejected.","triggerScenarios":"Calling client.xrange(name, '-', '+', count=0), count=-5, count=1.5, count='10', or count=None-equivalent truthy non-int. Any non-int or count<1 value passed as the count kwarg triggers it.","commonSituations":"Reading count from untyped config/env (os.environ returns str), passing a float from a computed ratio without int(), defaulting count to 0 meaning 'no limit' (0 is invalid; use None), or off-by-one when paginating streams.","solutions":["Pass an int >= 1 for count, or pass None / omit it when you want no limit.","Coerce untrusted input: count = int(count) and guard count is not None and count >= 1 before calling.","If you meant 'all entries', do not set count at all - None means unlimited."],"exampleFix":"# before\nclient.xrange('mystream', '-', '+', count=os.environ['XRANGE_COUNT'])\n# after\nc = int(os.environ['XRANGE_COUNT'])\nclient.xrange('mystream', '-', '+', count=c if c >= 1 else None)","handlingStrategy":"validation","validationCode":"def safe_xrange_count(count):\n    if count is None:\n        return None\n    if not isinstance(count, int) or isinstance(count, bool) or count < 1:\n        raise DataError('XRANGE count must be a positive int')\n    return count","typeGuard":"from typing import Union\n\ndef is_valid_xrange_count(c) -> bool:\n    return isinstance(c, int) and not isinstance(c, bool) and c >= 1","tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    client.xrange('s', '-', '+', count=user_count)\nexcept DataError as e:\n    if 'XRANGE count' in str(e):\n        logger.warning('invalid count %r, retrying unlimited', user_count)\n        client.xrange('s', '-', '+')\n    else:\n        raise","preventionTips":["Always coerce env/config values to int before passing as count.","Treat count=0 as None (unlimited), since 0 is invalid.","Unit-test stream helpers with 0, negative, float, and string inputs."],"tags":["streams","xrange","argument-validation","dataerror"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}