redis/redis-py · error · DataError
EXCLUDEEMPTY is not allowed with GROUPBY
Error message
EXCLUDEEMPTY is not allowed with GROUPBY
What it means
Raised by the TS.MRANGE/TS.MREVRANGE parameter builder when both exclude_empty=True and groupby are set. EXCLUDEEMPTY filters out empty series before grouping, which conflicts with GROUPBY semantics (it would drop groups). The library rejects the combination up front.
Source
Thrown at redis/commands/timeseries/commands.py:1424
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)
return params
@overload
def mrange(View on GitHub (pinned to da03cdc7e8)
Solutions
- Drop exclude_empty when using GROUPBY: set exclude_empty=False (the default).
- If you must exclude empty series, pre-filter the series via a TS.QUERYINDEX/QUERYLABELS lookup instead of EXCLUDEEMPTY.
- Keep GROUPBY and accept that empty groups may appear.
Example fix
// before
client.ts().mrange('-', '+', filters=f, groupby='region', reduce='sum', exclude_empty=True)
// after
client.ts().mrange('-', '+', filters=f, groupby='region', reduce='sum', exclude_empty=False) Defensive patterns
Strategy: validation
Validate before calling
def normalize_mrange_opts(groupby, exclude_empty):
if groupby is not None and exclude_empty:
return groupby, False # drop EXCLUDEEMPTY when grouping
return groupby, exclude_empty Type guard
def groupby_exclude_empty_compatible(groupby, exclude_empty) -> bool:
return not (exclude_empty and groupby is not None) Try / catch
try:
client.ts().mrange('-', '+', filters=f, groupby=g, reduce=r, exclude_empty=ee)
except Exception as e:
if 'EXCLUDEEMPTY' in str(e):
client.ts().mrange('-', '+', filters=f, groupby=g, reduce=r, exclude_empty=False)
else:
raise Prevention
- Never combine exclude_empty=True with groupby.
- Pre-filter empty series via QUERYINDEX instead of EXCLUDEEMPTY when grouping.
- Enforce mutual exclusion in option builders.
When it happens
Trigger: client.ts().mrange('-', '+', filters=f, groupby='region', reduce='sum', exclude_empty=True).
Common situations: Adding EXCLUDEEMPTY to reduce noise while also grouping; copying options from a non-grouped query into a grouped one; enabling both via a shared config dict.
Related errors
- GROUPBY is not allowed when multiple aggregators are specifi
- with_labels and select_labels cannot be provided together.
- At least one key must be provided.
- filters cannot be an empty collection; pass None to query al
- block_min_count requires block_milliseconds to be set; the B
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/fc7f318345da2fed.json.
Report an issue: GitHub.