{"record":{"id":"38ba60160a81d8da","repo":"Textualize/textual","slug":"unable-to-parse-filter-filter-r-as-query","errorCode":null,"errorMessage":"Unable to parse filter {filter!r} as query","messagePattern":"Unable to parse filter (.+?) as query","errorType":"validation","errorClass":"InvalidQueryFormat","httpStatus":null,"severity":"error","filePath":"src/textual/css/query.py","lineNumber":102,"sourceCode":"        Raises:\n            InvalidQueryFormat: If the format of the query is invalid.\n        \"\"\"\n        _rich_traceback_omit = True\n        self._node = node\n        self._nodes: list[QueryType] | None = None\n        self._filters: list[tuple[SelectorSet, ...]] = (\n            parent._filters.copy() if parent else []\n        )\n        self._excludes: list[tuple[SelectorSet, ...]] = (\n            parent._excludes.copy() if parent else []\n        )\n        self._deep = deep\n        if filter is not None:\n            try:\n                self._filters.append(parse_selectors(filter))\n            except TokenError:\n                # TODO: More helpful errors\n                raise InvalidQueryFormat(f\"Unable to parse filter {filter!r} as query\")\n\n        if exclude is not None:\n            try:\n                self._excludes.append(parse_selectors(exclude))\n            except TokenError:\n                raise InvalidQueryFormat(f\"Unable to parse filter {filter!r} as query\")\n\n    @property\n    def node(self) -> DOMNode:\n        \"\"\"The node being queried.\"\"\"\n        return self._node\n\n    @property\n    def nodes(self) -> list[QueryType]:\n        \"\"\"Lazily evaluate nodes.\"\"\"\n        from textual.widget import Widget\n\n        if self._nodes is None:","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/css/query.py#L84-L120","documentation":"QueryFilter/DOMQuery.__init__ parses its `filter` argument with parse_selectors; a TokenError from the selector tokenizer (malformed selector syntax) is converted to InvalidQueryFormat naming the filter string. This covers the filter= path.","triggerScenarios":"`query(\"Button\")` is fine, but `QueryFilter(\"Button>\">\")`, unbalanced parens/brackets, stray characters like `#id$`, or invalid pseudo-syntax raise this. Example: `screen.query(filter=\"Foo:hoover\")` with a bad combinator.","commonSituations":"Building selector strings dynamically (f-strings from user input) that produce invalid selector grammar; typos in combinators or pseudo-classes.","solutions":["Fix the selector syntax to valid Textual selectors (types, #id, .class, *, combinators '>', ' ', ',', pseudo-classes)","When building selectors from data, validate/escape components before concatenation","Catch InvalidQueryFormat to fall back to a default query for user-supplied selectors"],"exampleFix":"# before\nnodes = screen.query(\"Button>>Label\")\n# after\nnodes = screen.query(\"Button > Label\")","handlingStrategy":"try-catch","validationCode":"from textual.css.query import parse_selectors\ntry:\n    parse_selectors(selector)\n    ok = True\nexcept Exception:\n    ok = False","typeGuard":null,"tryCatchPattern":"from textual.css.query import InvalidQueryFormat\ntry:\n    nodes = screen.query(selector)\nexcept InvalidQueryFormat:\n    nodes = []  # or log and re-prompt","preventionTips":["Validate user-supplied selector strings with parse_selectors before querying"],"tags":["textual","query","selector","parse-error"],"backgroundTag":"invalid-selector-syntax","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}