Textualize/textual · critical · RuntimeError

Widget is missing attributes; have you called the constructo

Error message

Widget is missing attributes; have you called the constructor in your widget class?

What it means

Raised while walking up the DOM looking for the enclosing Screen: an AttributeError occurred while following _parent links, meaning the widget's internal attributes were never initialized. This almost always means a custom widget's __init__ did not call super().__init__().

Source

Thrown at src/textual/dom.py:802

    def screen(self) -> "Screen[object]":
        """The screen containing this node.

        Returns:
            A screen object.

        Raises:
            NoScreen: If this node isn't mounted (and has no screen).
        """
        # Get the node by looking up a chain of parents
        # Note that self.screen may not be the same as self.app.screen
        from textual.screen import Screen

        node: MessagePump | None = self
        try:
            while node is not None and not isinstance(node, Screen):
                node = node._parent
        except AttributeError:
            raise RuntimeError(
                "Widget is missing attributes; have you called the constructor in your widget class?"
            ) from None
        if not isinstance(node, Screen):
            raise NoScreen("node has no screen")
        return node

    @property
    def id(self) -> str | None:
        """The ID of this node, or None if the node has no ID."""
        return self._id

    @id.setter
    def id(self, new_id: str) -> str:
        """Sets the ID (may only be done once).

        Args:
            new_id: ID for this node.

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Add super().__init__(*args, **kwargs) as the first statement of the custom widget's __init__
  2. Verify no intermediate base class in the hierarchy swallows the constructor call
  3. If constructing raw DOMNode/Widget instances in tests, use the normal constructor path instead of __new__-style hacks

Example fix

# before
class MyWidget(Widget):
    def __init__(self, label):
        self.label = label  # forgot super().__init__()

# after
class MyWidget(Widget):
    def __init__(self, label: str):
        super().__init__()
        self.label = label
Defensive patterns

Strategy: validation

Validate before calling

# before touching screen-dependent APIs:
assert hasattr(widget, '_parent'), 'super().__init__() not called?'

Type guard

def is_initialized(node) -> bool:
    return hasattr(node, '_parent') and hasattr(node, '_nodes')

Prevention

When it happens

Trigger: Defining a widget subclass whose __init__ forgets to call super().__init__() (or Widget.__init__), then accessing widget.screen (directly or via any API that needs the screen, e.g. styles, refresh, posting messages).

Common situations: Custom widget with a custom constructor that sets attributes before/without calling the parent constructor; overriding __new__ or partially initializing objects in tests; copy-pasted widget code that drops the super() call.

Related errors


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