redis/redis-py · error · DataError
filters cannot be an empty collection; pass None to query al
Error message
filters cannot be an empty collection; pass None to query all indexed series.
What it means
Raised by TS.QUERYLABELS parameter building (_append_filter_expressions) when filters is passed as an explicitly empty collection. None means 'query all series' (FILTER omitted); an empty collection is ambiguous and would silently widen the query, so the library treats it as a usage error. Pass None to query everything, or a non-empty list of filter expressions.
Source
Thrown at redis/commands/timeseries/commands.py:1926
@staticmethod
def _append_filter_expressions(
params: list[EncodableT], filters: Iterable[str] | None
):
"""Append the optional FILTER clause for TS.QUERYLABELS.
``None`` omits ``FILTER`` entirely (the documented all-series query);
an explicitly empty collection is a local usage error, since silently
widening to all series would be surprising. Any iterable is accepted and
materialized once so single-pass iterators are handled correctly.
Expressions are passed through verbatim, without parsing, reordering, or
normalizing.
"""
if filters is None:
return
filters = list(filters)
if not filters:
raise DataError(
"filters cannot be an empty collection; pass None to query "
"all indexed series."
)
params.append("FILTER")
params.extend(filters)
@staticmethod
def _append_uncompressed(params: list[EncodableT], uncompressed: bool | None):
"""Append UNCOMPRESSED tag to params."""
if uncompressed:
params.extend(["ENCODING", "UNCOMPRESSED"])
@staticmethod
def _append_with_labels(
params: list[EncodableT],
with_labels: bool | None,
select_labels: list[str] | None,
):View on GitHub (pinned to da03cdc7e8)
Solutions
- Pass None (or omit the argument) to query all indexed series: client.ts().querylabels() or querylabels(filters=None).
- Provide at least one filter expression: querylabels(filters=['region=us']).
- Normalize optional input: filters = filters or None before calling.
Example fix
// before client.ts().querylabels(filters=selected_filters) # empty list // after client.ts().querylabels(filters=selected_filters or None)
Defensive patterns
Strategy: validation
Validate before calling
def coerce_filters(filters):
# None means 'all series'; empty collection is rejected by the lib
if filters is not None and len(list(filters)) == 0:
return None
return filters
# usage: client.ts().querylabels(filters=coerce_filters(f)) Type guard
def filters_ok(filters) -> bool:
return filters is None or len(list(filters)) > 0 Try / catch
try:
client.ts().querylabels(filters=f)
except Exception as e:
if 'empty collection' in str(e):
client.ts().querylabels() # query all
else:
raise Prevention
- Pass None, not [], when you mean 'all series'.
- Normalize optional filters: filters = filters or None.
- Remember [] is an error, None is valid.
When it happens
Trigger: client.ts().querylabels(filters=[]) or querylabels(filters=exprs) where exprs is an empty list. Also querylabels('region', filters=[]) for the VALUES form.
Common situations: Forwarding an optional filter list that resolved to empty; migrating from TS.QUERYINDEX which accepts different semantics; assuming [] means 'all'.
Related errors
- At least one key must be provided.
- GROUPBY is not allowed when multiple aggregators are specifi
- EXCLUDEEMPTY is not allowed with GROUPBY
- with_labels and select_labels cannot be provided together.
- 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/791f15a0030738fc.json.
Report an issue: GitHub.