redis/redis-py · error · DataError
AGGREGATION requires exactly one aggregation spec per key
Error message
AGGREGATION requires exactly one aggregation spec per key (expected {numkeys}, got {len(specs)}); a spec may list multiple comma-separated aggregators. What it means
Raised by _append_n_aggregation (TS.NRANGE / TS.NREVRANGE) when the number of aggregation specs does not equal the number of queried keys. NRANGE takes exactly one aggregation spec per key (each spec may itself be a comma-joined list of aggregators); a count mismatch is rejected client-side. The message reports expected (numkeys) vs received (len(specs)).
Solutions
- Provide exactly one spec per key: aggregators=['avg','max'] for two keys.
- For multiple aggregators on one key, comma-join them: aggregators='avg,max' for a single key.
- For a single-key query, a bare string is fine: aggregators='avg'.
Example fix
// before client.ts().nrange(['k1','k2'], f, t, aggregators='avg') // after client.ts().nrange(['k1','k2'], f, t, aggregators=['avg','max']) # multiple aggregators on a single key: client.ts().nrange(['k1'], f, t, aggregators='avg,max')
Defensive patterns
Strategy: validation
Validate before calling
if aggregators is not None:
specs = [aggregators] if isinstance(aggregators, str) else list(aggregators)
assert len(specs) == len(keys), f'{len(specs)} specs for {len(keys)} keys'
client.ts().nrange(keys, f, t, aggregators=aggregators) Try / catch
from redis.exceptions import DataError
try:
client.ts().nrange(keys, f, t, aggregators=aggregators)
except DataError:
aggregators = [aggregators] * len(keys) if isinstance(aggregators, str) else aggregators
client.ts().nrange(keys, f, t, aggregators=aggregators) Prevention
- Build one spec per key; comma-join within a spec for multiple aggregators.
- Do not assume a single aggregator broadcasts across keys.
When it happens
Trigger: Calling nrange(['k1','k2'], ...) with aggregators='avg' (one spec for two keys), or aggregators=['avg','max','sum'] (three specs for two keys). Passing a single string when multiple keys are present.
Common situations: Assuming a single aggregator broadcasts across all keys (the old behavior pre-RedisTimeSeries #2079). Mixing up NRANGE semantics with MRANGE. Off-by-one when building the spec list.
Related errors
- At least one key must be provided.
- GROUPBY is not allowed when multiple aggregators are…
- block_min_count requires block_milliseconds to be set; the…
- Both ignore_max_time_diff and ignore_max_val_diff must be…
- collect fields must be '*' or a non-empty list of names
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/cc7b0aa25a99ec39.
Report an issue: GitHub.
Appendix: source
Thrown at redis/commands/timeseries/commands.py:2062
bucket_size_msec: int | None,
numkeys: int,
):
"""Append the AGGREGATION clause for TS.NRANGE / TS.NREVRANGE.
These commands take exactly one aggregation spec token per queried key;
a single aggregator is never broadcast across keys. A spec token may hold
several comma-separated aggregators, so the wire form is e.g.
``AGGREGATION avg,max sum 1000`` for two keys -- key 0 aggregated by both
``avg`` and ``max``, key 1 by ``sum``. Pass one spec string per key, each
optionally comma-joined (``["avg,max", "sum"]``); a bare string is the
spec for a single-key query. (Matches RedisTimeSeries PR #2079, which
replaced the earlier single comma-joined / broadcast token.)
"""
if aggregators is None:
return
specs = [aggregators] if isinstance(aggregators, str) else list(aggregators)
if len(specs) != numkeys:
raise DataError(
"AGGREGATION requires exactly one aggregation spec per key "
f"(expected {numkeys}, got {len(specs)}); a spec may list "
"multiple comma-separated aggregators."
)
params.extend(["AGGREGATION", *specs, bucket_size_msec])
@staticmethod
def _append_chunk_size(params: list[EncodableT], chunk_size: int | None):
"""Append CHUNK_SIZE property to params."""
if chunk_size is not None:
params.extend(["CHUNK_SIZE", chunk_size])
@staticmethod
def _append_duplicate_policy(
params: list[EncodableT], duplicate_policy: str | None
):
"""Append DUPLICATE_POLICY property to params."""
if duplicate_policy is not None:View on GitHub (pinned to 6a6b581b48)