redis/redis-py · error · DataError
block_min_count requires block_milliseconds to be set; the B
Error message
block_min_count requires block_milliseconds to be set; the BLOCK group is all-or-nothing.
What it means
Raised by _append_block (used by TS.READ) when block_min_count is set but block_milliseconds is None. The BLOCK group on the wire is all-or-nothing: blocking is opted into via block_milliseconds, and min_count defaults to 1 only when blocking is enabled. Supplying a threshold without enabling blocking is a usage error.
Source
Thrown at redis/commands/timeseries/commands.py:1999
if count is not None:
params.extend(["COUNT", count])
@staticmethod
def _append_block(
params: list[EncodableT],
block_milliseconds: int | None,
block_min_count: int | None,
):
"""Append the BLOCK group to params.
The BLOCK group is all-or-nothing: when blocking is requested
(`block_milliseconds` is set), both `milliseconds` and `min_count` are
always emitted, with `min_count` defaulting to 1. There is no standalone
MIN_COUNT keyword in this command.
"""
if block_milliseconds is None:
if block_min_count is not None:
raise DataError(
"block_min_count requires block_milliseconds to be set; the "
"BLOCK group is all-or-nothing."
)
return
min_count = 1 if block_min_count is None else block_min_count
params.extend(["BLOCK", block_milliseconds, min_count])
@staticmethod
def _append_max_count(params: list[EncodableT], max_count: int | None):
"""Append MAX_COUNT property to params."""
if max_count is not None:
params.extend(["MAX_COUNT", max_count])
@staticmethod
def _append_timestamp(params: list[EncodableT], timestamp: int | None):
"""Append TIMESTAMP property to params."""
if timestamp is not None:
params.extend(["TIMESTAMP", timestamp])View on GitHub (pinned to da03cdc7e8)
Solutions
- Set block_milliseconds alongside block_min_count: client.ts().read('key', '$', block_milliseconds=5000, block_min_count=5).
- If you do not want blocking, remove block_min_count entirely.
- Also raise the client socket_timeout above block_milliseconds to avoid a premature TimeoutError.
Example fix
// before
client.ts().read('key', '$', block_min_count=5)
// after
client.ts().read('key', '$', block_milliseconds=5000, block_min_count=5) Defensive patterns
Strategy: validation
Validate before calling
def normalize_block(block_ms, block_min_count):
if block_min_count is not None and block_ms is None:
raise ValueError("block_min_count requires block_milliseconds")
return block_ms, block_min_count
# usage: client.ts().read('k', '$', *normalize_block(ms, mc)) Type guard
def block_args_valid(block_ms, block_min_count) -> bool:
return block_ms is not None or block_min_count is None Try / catch
try:
client.ts().read('k', '$', block_min_count=mc)
except Exception as e:
if 'block_min_count requires' in str(e):
client.ts().read('k', '$', block_milliseconds=5000, block_min_count=mc)
else:
raise Prevention
- Always set block_milliseconds when setting block_min_count.
- Raise socket_timeout above the block window when blocking.
- Keep the BLOCK group as one unit in config.
When it happens
Trigger: client.ts().read('key', '$', block_min_count=5) with block_milliseconds left as None.
Common situations: Configuring the unblock threshold but forgetting the block duration; passing a partial BLOCK config from a dict that omitted milliseconds; assuming min_count alone enables blocking.
Related errors
- At least one key must be provided.
- GROUPBY is not allowed when multiple aggregators are specifi
- EXCLUDEEMPTY is not allowed with GROUPBY
- filters cannot be an empty collection; pass None to query al
- with_labels and select_labels cannot be provided together.
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/a52eef52d1e94e6d.json.
Report an issue: GitHub.