{"record":{"id":"387fe90bbcafebf0","repo":"redis/redis-py","slug":"xread-count-must-be-a-positive-integer","errorCode":null,"errorMessage":"XREAD count must be a positive integer","messagePattern":"XREAD count must be a positive integer","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":7913,"sourceCode":"\n        max_size: if set, a soft cap on the total server reply size in bytes\n                  across all streams combined. Measured server-side including\n                  protocol overhead, so it is not an exact application-payload\n                  size guarantee; a single available entry larger than the cap\n                  may still be returned. Must be a positive integer. Requires\n                  Redis >= 8.10.0.\n\n        For more information, see https://redis.io/commands/xread\n        \"\"\"\n        pieces = []\n        if block is not None:\n            if not isinstance(block, int) or block < 0:\n                raise DataError(\"XREAD block must be a non-negative integer\")\n            pieces.append(b\"BLOCK\")\n            pieces.append(str(block))\n        if count is not None:\n            if not isinstance(count, int) or count < 1:\n                raise DataError(\"XREAD count must be a positive integer\")\n            pieces.append(b\"COUNT\")\n            pieces.append(str(count))\n        if max_count is not None:\n            if not isinstance(max_count, int) or max_count < 1:\n                raise DataError(\"XREAD max_count must be a positive integer\")\n            if count is not None and max_count < count:\n                raise DataError(\n                    \"XREAD max_count must be greater than or equal to count\"\n                )\n            pieces.append(b\"MAXCOUNT\")\n            pieces.append(str(max_count))\n        if max_size is not None:\n            if not isinstance(max_size, int) or max_size < 1:\n                raise DataError(\"XREAD max_size must be a positive integer\")\n            pieces.append(b\"MAXSIZE\")\n            pieces.append(str(max_size))\n        if not isinstance(streams, dict) or len(streams) == 0:\n            raise DataError(\"XREAD streams must be a non empty dict\")","sourceCodeStart":7895,"sourceCodeEnd":7931,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L7895-L7931","documentation":"Raised by xread() (redis/commands/core.py:7913) as a DataError when count is not an int or is < 1. count is the per-stream COUNT limit; unlike block it must be strictly positive. Validated before the XREAD command is assembled.","triggerScenarios":"Calling client.xread(streams, count=0), count=-1, count='100', or count=50.0. count=None means no limit.","commonSituations":"Pagination loop that decrements count and hits 0, passing a float batch size, or env-sourced string value. Distinguishing count (per-stream limit) from max_count (cumulative cap) - both must be positive ints.","solutions":["Pass an int >= 1 for count, or None for no per-stream limit.","In pagination, break or recompute when remaining <= 0 rather than passing 0.","Coerce env input: count = int(val) if val else None."],"exampleFix":"# before\nremaining = total - seen\nclient.xread(streams, count=remaining)\n# after\nif remaining >= 1:\n    client.xread(streams, count=remaining)\nelse:\n    break","handlingStrategy":"validation","validationCode":"def safe_xread_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('XREAD count must be a positive int')\n    return count","typeGuard":"def is_valid_xread_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.xread(streams, count=batch)\nexcept DataError as e:\n    if 'XREAD count' in str(e):\n        client.xread(streams, count=100)  # sane default\n    else:\n        raise","preventionTips":["In pagination loops, break when remaining < 1 instead of passing 0.","Distinguish count (per-stream) from max_count (cumulative) - both must be >= 1.","Coerce env-sourced batch sizes to int."],"tags":["streams","xread","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"}