{"record":{"id":"b6f35d58b4668e7d","repo":"Textualize/textual","slug":"widget-is-missing-attributes-have-you-called-the","errorCode":null,"errorMessage":"Widget is missing attributes; have you called the constructor in your widget class?","messagePattern":"Widget is missing attributes; have you called the constructor in your widget class\\?","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"src/textual/dom.py","lineNumber":802,"sourceCode":"    def screen(self) -> \"Screen[object]\":\n        \"\"\"The screen containing this node.\n\n        Returns:\n            A screen object.\n\n        Raises:\n            NoScreen: If this node isn't mounted (and has no screen).\n        \"\"\"\n        # Get the node by looking up a chain of parents\n        # Note that self.screen may not be the same as self.app.screen\n        from textual.screen import Screen\n\n        node: MessagePump | None = self\n        try:\n            while node is not None and not isinstance(node, Screen):\n                node = node._parent\n        except AttributeError:\n            raise RuntimeError(\n                \"Widget is missing attributes; have you called the constructor in your widget class?\"\n            ) from None\n        if not isinstance(node, Screen):\n            raise NoScreen(\"node has no screen\")\n        return node\n\n    @property\n    def id(self) -> str | None:\n        \"\"\"The ID of this node, or None if the node has no ID.\"\"\"\n        return self._id\n\n    @id.setter\n    def id(self, new_id: str) -> str:\n        \"\"\"Sets the ID (may only be done once).\n\n        Args:\n            new_id: ID for this node.\n","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/dom.py#L784-L820","documentation":"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__().","triggerScenarios":"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).","commonSituations":"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.","solutions":["Add super().__init__(*args, **kwargs) as the first statement of the custom widget's __init__","Verify no intermediate base class in the hierarchy swallows the constructor call","If constructing raw DOMNode/Widget instances in tests, use the normal constructor path instead of __new__-style hacks"],"exampleFix":"# before\nclass MyWidget(Widget):\n    def __init__(self, label):\n        self.label = label  # forgot super().__init__()\n\n# after\nclass MyWidget(Widget):\n    def __init__(self, label: str):\n        super().__init__()\n        self.label = label","handlingStrategy":"validation","validationCode":"# before touching screen-dependent APIs:\nassert hasattr(widget, '_parent'), 'super().__init__() not called?'","typeGuard":"def is_initialized(node) -> bool:\n    return hasattr(node, '_parent') and hasattr(node, '_nodes')","tryCatchPattern":null,"preventionTips":["Always call super().__init__() first in custom widget constructors","Lint for __init__ without super() in widget subclasses","Run app smoke tests that mount every custom widget"],"tags":["textual","constructor","super","widget-init"],"backgroundTag":"missing-super-init-call","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}