redis/redis-py · error · DataError

GROUPBY is not allowed when multiple aggregators are…

Error message

GROUPBY is not allowed when multiple aggregators are specified

What it means

Raised by the TS.MRANGE / TS.MREVRANGE parameter builder when groupby is set AND aggregation_type is a list with more than one entry. GROUPBY/REDUCE reduces multiple series into one bucket; combining it with multiple aggregators (a multi-aggregator spec) is semantically invalid and rejected client-side.

Solutions

  1. Drop groupby/reduce when you need multiple aggregators.
  2. Use a single aggregator (string, or a one-element list) when you need GROUPBY.
  3. Run two separate mrange calls if you need both multiple aggregators and grouping.

Example fix

// before
client.ts().mrange(f, t, filters,
    aggregation_type=['avg','max'], groupby='region', reduce='avg')
// after  (choose one)
client.ts().mrange(f, t, filters,
    aggregation_type='avg', groupby='region', reduce='avg')
# or drop grouping for multi-aggregator
client.ts().mrange(f, t, filters, aggregation_type=['avg','max'])
Defensive patterns

Strategy: validation

Validate before calling

if groupby and isinstance(aggregation_type, list) and len(aggregation_type) > 1:
    raise ValueError('cannot combine groupby with multiple aggregators')
client.ts().mrange(...)

Try / catch

from redis.exceptions import DataError
try:
    client.ts().mrange(..., aggregation_type=agg, groupby=groupby, reduce=reduce)
except DataError:
    agg = agg[0] if isinstance(agg, list) else agg
    client.ts().mrange(..., aggregation_type=agg, groupby=groupby, reduce=reduce)

Prevention

When it happens

Trigger: Calling mrange(..., aggregation_type=['avg','max'], groupby='region', reduce='avg'). A list of aggregators with length > 1 plus any groupby value.

Common situations: Migrating from a single-aggregator call to the new multi-aggregator feature while still passing groupby. Copying NRANGE-style aggregator lists into an MRANGE with grouping.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/09808a3faa3d1ef6. Report an issue: GitHub.

Appendix: source

Thrown at redis/commands/timeseries/commands.py:1420

        filter_by_ts: List[int] | None,
        filter_by_min_value: int | None,
        filter_by_max_value: int | None,
        groupby: str | None,
        reduce: str | None,
        select_labels: List[str] | None,
        align: int | str | None,
        latest: bool | None,
        bucket_timestamp: str | None,
        empty: bool | None,
        exclude_empty: bool | None,
    ):
        """Create TS.MRANGE and TS.MREVRANGE arguments."""
        if (
            groupby is not None
            and isinstance(aggregation_type, list)
            and len(aggregation_type) > 1
        ):
            raise DataError(
                "GROUPBY is not allowed when multiple aggregators are specified"
            )
        if exclude_empty and groupby is not None:
            raise DataError("EXCLUDEEMPTY is not allowed with GROUPBY")
        params: list[EncodableT] = [from_time, to_time]
        self._append_latest(params, latest)
        self._append_filer_by_ts(params, filter_by_ts)
        self._append_filer_by_value(params, filter_by_min_value, filter_by_max_value)
        self._append_with_labels(params, with_labels, select_labels)
        self._append_count(params, count)
        self._append_align(params, align)
        self._append_aggregation(params, aggregation_type, bucket_size_msec)
        self._append_bucket_timestamp(params, bucket_timestamp)
        self._append_empty(params, empty)
        self._append_exclude_empty(params, exclude_empty)
        params.extend(["FILTER"])
        params += filters
        self._append_groupby_reduce(params, groupby, reduce)

View on GitHub (pinned to 6a6b581b48)