redis/redis-py · error · DataError
XRANGE count must be a positive integer
Error message
XRANGE count must be a positive integer
What it means
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.
Source
Thrown at redis/commands/core.py:7845
Read stream values within an interval.
name: name of the stream.
start: first stream ID. defaults to '-',
meaning the earliest available.
finish: last stream ID. defaults to '+',
meaning the latest available.
count: if set, only return this many items, beginning with the
earliest available.
For more information, see https://redis.io/commands/xrange
"""
pieces = [min, max]
if count is not None:
if not isinstance(count, int) or count < 1:
raise DataError("XRANGE count must be a positive integer")
pieces.append(b"COUNT")
pieces.append(str(count))
return self.execute_command("XRANGE", name, *pieces, keys=[name])
@overload
def xread(
self: SyncClientProtocol,
streams: Dict[KeyT, StreamIdT],
count: int | None = None,
block: int | None = None,
max_count: int | None = None,
max_size: int | None = None,
) -> XReadResponse: ...
@overload
def xread(
self: AsyncClientProtocol,View on GitHub (pinned to da03cdc7e8)
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.
Example fix
// before
client.xrange("s", "-", "+", count="50")
// after
client.xrange("s", "-", "+", count=50) Defensive patterns
Strategy: validation
Validate before calling
def normalize_count(v):
if v is None:
return None
if not isinstance(v, int) or isinstance(v, bool):
raise TypeError(f"count must be int, got {type(v)}")
if v < 1:
raise ValueError(f"count must be >= 1, got {v}")
return v
count = normalize_count(raw_count)
client.xrange("s", "-", "+", count=count) Type guard
def is_positive_int(v) -> bool:
return isinstance(v, int) and not isinstance(v, bool) and v >= 1 Try / catch
from redis.exceptions import DataError
try:
client.xrange("s", "-", "+", count=count)
except DataError as e:
if "XRANGE count" in str(e):
count = int(count)
client.xrange("s", "-", "+", count=count) if count >= 1 else None
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- XREAD block must be a non-negative integer
- XREAD count must be a positive integer
- XREAD max_count must be a positive integer
- CLIENT KILL type must be one of {client_types!r}
- CLIENT KILL skipme must be a bool
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/24924b8a8d482a8c.json.
Report an issue: GitHub.