redis/redis-py · error · DataError
XREAD block must be a non-negative integer
Error message
XREAD block must be a non-negative integer
What it means
Raised by xread() (redis/commands/core.py:7908) as a DataError when block is not an int or is negative. block is the BLOCK milliseconds argument to XREAD; 0 means block indefinitely, so the lower bound is inclusive (>= 0). Validation happens client-side before the command is built.
Solutions
- Pass a non-negative int (>= 0) for block, or None to make the call non-blocking.
- Remember block=0 means block indefinitely; pass None when you want no blocking.
- Clamp computed timeouts: block = max(0, int(deadline - now_ms)).
Example fix
# before
client.xread({'mystream': '$'}, block=deadline_ms - now_ms)
# after
block_ms = max(0, int(deadline_ms - now_ms))
client.xread({'mystream': '$'}, block=block_ms) Defensive patterns
Strategy: validation
Validate before calling
def safe_xread_block(block):
if block is None:
return None
if not isinstance(block, int) or isinstance(block, bool) or block < 0:
raise DataError('XREAD block must be a non-negative int')
return block Type guard
def is_valid_xread_block(b) -> bool:
return isinstance(b, int) and not isinstance(b, bool) and b >= 0 Try / catch
from redis.exceptions import DataError
try:
client.xread(streams, block=timeout)
except DataError as e:
if 'block' in str(e):
client.xread(streams) # fall back to non-blocking
else:
raise Prevention
- Remember block=0 means block forever; use None for non-blocking.
- Clamp computed timeouts to max(0, ...) to avoid negatives from clock skew.
- Keep block as an int through your pipeline - do not stringify.
When it happens
Trigger: Calling client.xread(streams, block=-1), block=1.5, block='5000', or block=True. block=0 is valid and means 'block forever'.
Common situations: Reading block timeout from env/config as a string, computing a negative timeout from a timestamp diff that went negative (clock skew), or treating block=0 as 'no block' (it actually means infinite block - use None for non-blocking).
Related errors
- XREAD count must be a positive integer
- XREAD max_count must be a positive integer
- XRANGE count must be a positive integer
- Invalid FPHA type: . Must be one of
- No key specified
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/ef471467a7ec22cd.
Report an issue: GitHub.
Appendix: source
Thrown at redis/commands/core.py:7908
max_count: if set, cap the total number of entries returned across all
streams combined. Unlike ``count`` (a per-stream limit),
this is a cumulative cap over the whole reply. Must be a
positive integer and, when ``count`` is also set, must be
greater than or equal to ``count``. Requires Redis >= 8.10.0.
max_size: if set, a soft cap on the total server reply size in bytes
across all streams combined. Measured server-side including
protocol overhead, so it is not an exact application-payload
size guarantee; a single available entry larger than the cap
may still be returned. Must be a positive integer. Requires
Redis >= 8.10.0.
For more information, see https://redis.io/commands/xread
"""
pieces = []
if block is not None:
if not isinstance(block, int) or block < 0:
raise DataError("XREAD block must be a non-negative integer")
pieces.append(b"BLOCK")
pieces.append(str(block))
if count is not None:
if not isinstance(count, int) or count < 1:
raise DataError("XREAD count must be a positive integer")
pieces.append(b"COUNT")
pieces.append(str(count))
if max_count is not None:
if not isinstance(max_count, int) or max_count < 1:
raise DataError("XREAD max_count must be a positive integer")
if count is not None and max_count < count:
raise DataError(
"XREAD max_count must be greater than or equal to count"
)
pieces.append(b"MAXCOUNT")
pieces.append(str(max_count))
if max_size is not None:
if not isinstance(max_size, int) or max_size < 1:View on GitHub (pinned to 6a6b581b48)