Textualize/textual · error · NoMatches

No child found with id={id!r}

Error message

No child found with id={id!r}

What it means

get_child_by_id searches only immediate children by their id attribute; NoMatches is raised when no direct child carries that id (grandchildren are not searched).

Source

Thrown at src/textual/widget.py:1109

    def get_child_by_id(
        self, id: str, expect_type: type[ExpectType] | None = None
    ) -> ExpectType | Widget:
        """Return the first child (immediate descendent) of this node with the given ID.

        Args:
            id: The ID of the child.
            expect_type: Require the object be of the supplied type, or None for any type.

        Returns:
            The first child of this node with the ID.

        Raises:
            NoMatches: if no children could be found for this ID
            WrongType: if the wrong type was found.
        """
        child = self._get_dom_base()._nodes._get_by_id(id)
        if child is None:
            raise NoMatches(f"No child found with id={id!r}")
        if expect_type is None:
            return child
        if not isinstance(child, expect_type):
            raise WrongType(
                f"Child with id={id!r} is the wrong type; expected type {expect_type.__name__!r}, found {child}"
            )
        return child

    if TYPE_CHECKING:

        @overload
        def get_widget_by_id(self, id: str) -> Widget: ...

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

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Use query_one("#id") or get_widget_by_id for deep descendants
  2. Verify the id is set on an immediate child in compose()
  3. Pass the id without the '#' prefix

Example fix

# before
child = self.get_child_by_id("inner")
# after
child = self.query_one("#inner")
Defensive patterns

Strategy: validation

Validate before calling

child = self._get_dom_base()._nodes._get_by_id(id)
if child is None:
    child = self.query_one(f"#{id}")  # fall back to deep search

Try / catch

try:
    w = parent.get_child_by_id("x")
except NoMatches:
    w = parent.query_one("#x")

Prevention

When it happens

Trigger: Calling get_child_by_id("x") where the id exists deeper in the tree, on a different parent, or was never set/has a typo.

Common situations: Assuming deep search like query(); ids set in compose() of a grandchild; leading '#' accidentally included in the id string.

Related errors


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