Textualize/textual · error · WrongType

Query value is the wrong type; expected type {expect_type.__

Error message

Query value is the wrong type; expected type {expect_type.__name__!r}, found {first}

What it means

DOMNode.query_one / DOMQuery.first checks the first matched node against the optional expect_type; a mismatch raises WrongType stating the expected class and the actual node. This is the type-safety guard for query_one[T](...) style access so callers can rely on the returned widget's interface.

Source

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

        """Get the *first* matching node.

        Args:
            expect_type: Require matched node is of this type,
                or None for any type.

        Raises:
            WrongType: If the wrong type was found.
            NoMatches: If there are no matching nodes in the query.

        Returns:
            The matching Widget.
        """
        _rich_traceback_omit = True
        if self.nodes:
            first = self.nodes[0]
            if expect_type is not None:
                if not isinstance(first, expect_type):
                    raise WrongType(
                        f"Query value is the wrong type; expected type {expect_type.__name__!r}, found {first}"
                    )
            return first
        else:
            raise NoMatches(f"No nodes match {self!r} on {self.node!r}")

    if TYPE_CHECKING:

        @overload
        def only_one(self) -> QueryType: ...

        @overload
        def only_one(self, expect_type: type[ExpectType]) -> ExpectType: ...

    def only_one(
        self, expect_type: type[ExpectType] | None = None
    ) -> QueryType | ExpectType:
        """Get the *only* matching node.

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Change expect_type to the actual widget class (or a base class it inherits from)
  2. Change the selector to match a node of the expected type (e.g. add an id/class to the right widget)
  3. Drop expect_type and branch on isinstance if heterogeneous matches are legitimate

Example fix

# before
header = self.query_one("#header", Static)  # WrongType if it's a Label
# after
from textual.widgets import Label
header = self.query_one("#header", Label)
Defensive patterns

Strategy: type-guard

Validate before calling

node = screen.query(selector).first() if screen.query(selector).nodes else None
if node is not None and isinstance(node, Static):
    ...

Type guard

def is_widget_type(node, cls) -> bool:
    return isinstance(node, cls)

Try / catch

from textual.css.query import WrongType, NoMatches
try:
    w = self.query_one(sel, Static)
except WrongType:
    w = self.query_one(sel)  # inspect actual type

Prevention

When it happens

Trigger: `self.query_one("#header", Static)` when #header is actually a Label subclass-less mismatch like a DataTable; `query_one("Button")` matching a custom widget not subclassing Button; generic query_one[Static] on an Input.

Common situations: DOM changes where a widget in the markup/CSS was swapped for another type; copy-pasting query_one calls between screens; expect_type omitted then added later incorrectly.

Related errors


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