Textualize/textual · error · NoMatches
No nodes match {self!r} on {self.node!r}
Error message
No nodes match {self!r} on {self.node!r} What it means
first() raises NoMatches when the selector matched zero nodes on the queried DOM node. This is the canonical 'selector found nothing' error for query_one/first, including the query and node in the message for debugging.
Source
Thrown at src/textual/css/query.py:249
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.
Args:
expect_type: Require matched node is of this type,
or None for any type.
View on GitHub (pinned to 06dbeef4bb)
Solutions
- Verify the selector matches something in the current DOM (ids spelled the same, widget actually composed)
- Move the query to after mounting — e.g. on_mount of the container, or call_before adding with mount and use the returned widget
- Use query(...).first() guarded, or catch NoMatches and compose/mount the missing widget on demand
Example fix
# before
def on_mount(self) -> None:
self.query_one("#late").focus() # NoMatches
# after
def on_mount(self) -> None:
self.call_after_refresh(self._focus_late)
def _focus_late(self) -> None:
self.query_one("#late").focus() Defensive patterns
Strategy: try-catch
Validate before calling
matches = screen.query(selector).nodes
if matches:
node = matches[0] Try / catch
from textual.css.query import NoMatches
try:
w = self.query_one("#id")
except NoMatches:
w = None Prevention
- Defer queries until after mount (call_after_refresh); double-check ids match compose()
When it happens
Trigger: `self.query_one("#submit")` before the widget is mounted or when the id is misspelled; querying a selector that exists only after compose() completes; querying a removed widget.
Common situations: Querying during on_mount before children mount (ordering), wrong/renamed ids, conditional widgets not yet created, or querying the wrong screen/node.
Related errors
- No nodes match {self!r} on dom{self.node!r}
- No nodes match {query_selector!r} on {base_node!r}
- Node matching {query_selector!r} is the wrong type; expected
- Call to query_one resulted in more than one matched node
- Unable to parse filter {filter!r} as query
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/dfa5b6253d302865.
Report an issue: GitHub.