Textualize/textual · error · WidgetError

A widget can't be its own parent

Error message

A widget can't be its own parent

What it means

Widget constructor guard: a widget instance was passed as one of its own children, which would create a self-referential DOM cycle.

Source

Thrown at src/textual/widget.py:498

        self._styles_cache = StylesCache()
        self._rich_style_cache: dict[tuple[str, ...], tuple[Style, Style]] = {}
        self._visual_style_cache: dict[tuple[str, ...], VisualStyle] = {}

        self._tooltip: VisualType | None = None
        """The tooltip content."""
        self.absolute_offset: Offset | None = None
        """Force an absolute offset for the widget (used by tooltips)."""

        self._scrollbar_changes: set[tuple[bool, bool]] = set()
        """Used to stabilize scrollbars."""
        super().__init__(
            name=name,
            id=id,
            classes=self.DEFAULT_CLASSES if classes is None else classes,
        )

        if self in children:
            raise WidgetError("A widget can't be its own parent")

        for child in children:
            if not isinstance(child, Widget):
                raise TypeError(
                    f"Widget positional arguments must be Widget subclasses; not {child!r}"
                )
        self._pending_children = list(children)
        self.set_reactive(Widget.disabled, disabled)
        if self.BORDER_TITLE:
            self.border_title = self.BORDER_TITLE
        if self.BORDER_SUBTITLE:
            self.border_subtitle = self.BORDER_SUBTITLE

        self.lock = RLock()
        """`asyncio` lock to be used to synchronize the state of the widget.

        Two different tasks might call methods on a widget at the same time, which
        might result in a race condition.

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Remove the self-reference from the children list
  2. Build the tree top-down: create children first, then the parent
  3. Use mount() after construction for dynamic structures

Example fix

# before
children = [panel]
box = Container(box, *children)  # oops
# after
box = Container(*children)
Defensive patterns

Strategy: validation

Validate before calling

assert all(child is not self for child in children)

Prevention

When it happens

Trigger: Widget(children=[...]) where the list contains the widget being constructed, e.g. via aliasing or building containers imperatively before init completes.

Common situations: Dynamic child lists that accidentally include 'self' due to variable reuse or a copy-paste in list building.

Related errors


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