{"record":{"id":"791f15a0030738fc","repo":"redis/redis-py","slug":"filters-cannot-be-an-empty-collection-pass-none-t","errorCode":null,"errorMessage":"filters cannot be an empty collection; pass None to query all indexed series.","messagePattern":"filters cannot be an empty collection; pass None to query all indexed series\\.","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/timeseries/commands.py","lineNumber":1926,"sourceCode":"\n    @staticmethod\n    def _append_filter_expressions(\n        params: list[EncodableT], filters: Iterable[str] | None\n    ):\n        \"\"\"Append the optional FILTER clause for TS.QUERYLABELS.\n\n        ``None`` omits ``FILTER`` entirely (the documented all-series query);\n        an explicitly empty collection is a local usage error, since silently\n        widening to all series would be surprising. Any iterable is accepted and\n        materialized once so single-pass iterators are handled correctly.\n        Expressions are passed through verbatim, without parsing, reordering, or\n        normalizing.\n        \"\"\"\n        if filters is None:\n            return\n        filters = list(filters)\n        if not filters:\n            raise DataError(\n                \"filters cannot be an empty collection; pass None to query \"\n                \"all indexed series.\"\n            )\n        params.append(\"FILTER\")\n        params.extend(filters)\n\n    @staticmethod\n    def _append_uncompressed(params: list[EncodableT], uncompressed: bool | None):\n        \"\"\"Append UNCOMPRESSED tag to params.\"\"\"\n        if uncompressed:\n            params.extend([\"ENCODING\", \"UNCOMPRESSED\"])\n\n    @staticmethod\n    def _append_with_labels(\n        params: list[EncodableT],\n        with_labels: bool | None,\n        select_labels: list[str] | None,\n    ):","sourceCodeStart":1908,"sourceCodeEnd":1944,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/timeseries/commands.py#L1908-L1944","documentation":"Raised by _append_filter_expressions (used by TS.QUERYLABELS) when filters is an explicitly empty collection. None means 'query all indexed series' (FILTER omitted); an empty list is treated as a likely caller bug because silently widening to all series would be surprising.","triggerScenarios":"Calling client.ts().querylabels(filters=[]) or querylabels(filters=iter([])). Passing a list that resolved to empty.","commonSituations":"Building filters from user input that produced no expressions. Mistakenly passing an empty list to mean 'no filter'.","solutions":["Pass None (or omit filters) to query all indexed series.","Pass a non-empty list of filter expressions.","Guard dynamic filters: filters = filter_list or None."],"exampleFix":"// before\nclient.ts().querylabels(filters=[])\n// after\nclient.ts().querylabels(filters=None)\n# or\nclient.ts().querylabels(filters=filter_list or None)","handlingStrategy":"validation","validationCode":"filters = filters if filters else None\nclient.ts().querylabels(filters=filters)","typeGuard":null,"tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    client.ts().querylabels(filters=filters)\nexcept DataError:\n    client.ts().querylabels(filters=None)","preventionTips":["Use None (not []) to mean 'no filter'.","Normalize empty iterables to None at call boundaries."],"tags":["redistimeseries","querylabels","filter","argument-validation"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}