Textualize/textual · error · InvalidQueryFormat

Unable to parse filter {filter!r} as query

Error message

Unable to parse filter {filter!r} as query

What it means

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.

Source

Thrown at src/textual/css/query.py:102

        Raises:
            InvalidQueryFormat: If the format of the query is invalid.
        """
        _rich_traceback_omit = True
        self._node = node
        self._nodes: list[QueryType] | None = None
        self._filters: list[tuple[SelectorSet, ...]] = (
            parent._filters.copy() if parent else []
        )
        self._excludes: list[tuple[SelectorSet, ...]] = (
            parent._excludes.copy() if parent else []
        )
        self._deep = deep
        if filter is not None:
            try:
                self._filters.append(parse_selectors(filter))
            except TokenError:
                # TODO: More helpful errors
                raise InvalidQueryFormat(f"Unable to parse filter {filter!r} as query")

        if exclude is not None:
            try:
                self._excludes.append(parse_selectors(exclude))
            except TokenError:
                raise InvalidQueryFormat(f"Unable to parse filter {filter!r} as query")

    @property
    def node(self) -> DOMNode:
        """The node being queried."""
        return self._node

    @property
    def nodes(self) -> list[QueryType]:
        """Lazily evaluate nodes."""
        from textual.widget import Widget

        if self._nodes is None:

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Fix the selector syntax to valid Textual selectors (types, #id, .class, *, combinators '>', ' ', ',', pseudo-classes)
  2. When building selectors from data, validate/escape components before concatenation
  3. Catch InvalidQueryFormat to fall back to a default query for user-supplied selectors

Example fix

# before
nodes = screen.query("Button>>Label")
# after
nodes = screen.query("Button > Label")
Defensive patterns

Strategy: try-catch

Validate before calling

from textual.css.query import parse_selectors
try:
    parse_selectors(selector)
    ok = True
except Exception:
    ok = False

Try / catch

from textual.css.query import InvalidQueryFormat
try:
    nodes = screen.query(selector)
except InvalidQueryFormat:
    nodes = []  # or log and re-prompt

Prevention

When it happens

Trigger: `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.

Common situations: Building selector strings dynamically (f-strings from user input) that produce invalid selector grammar; typos in combinators or pseudo-classes.

Understand the failure class

Related errors


AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27). Data as JSON: /api/errors/38ba60160a81d8da. Report an issue: GitHub.