{"record":{"id":"2b363cca7a62953b","repo":"Textualize/textual","slug":"descendant-with-id-id-r-is-the-wrong-type-expec","errorCode":null,"errorMessage":"Descendant with id={id!r} is the wrong type; expected type {expect_type.__name__!r}, found {widget}","messagePattern":"Descendant with id=(.+?) is the wrong type; expected type (.+?), found (.+?)","errorType":"exception","errorClass":"WrongType","httpStatus":null,"severity":"error","filePath":"src/textual/widget.py","lineNumber":1149,"sourceCode":"        \"\"\"Return the first descendant widget with the given ID.\n\n        Performs a depth-first search rooted at this widget.\n\n        Args:\n            id: The ID to search for in the subtree.\n            expect_type: Require the object be of the supplied type, or None for any type.\n\n        Returns:\n            The first descendant encountered with this ID.\n\n        Raises:\n            NoMatches: if no children could be found for this ID.\n            WrongType: if the wrong type was found.\n        \"\"\"\n\n        widget = self.query_one(f\"#{id}\")\n        if expect_type is not None and not isinstance(widget, expect_type):\n            raise WrongType(\n                f\"Descendant with id={id!r} is the wrong type; expected type {expect_type.__name__!r}, found {widget}\"\n            )\n        return widget\n\n    def get_child_by_type(self, expect_type: type[ExpectType]) -> ExpectType:\n        \"\"\"Get the first immediate child of a given type.\n\n        Only returns exact matches, and so will not match subclasses of the given type.\n\n        Args:\n            expect_type: The type of the child to search for.\n\n        Raises:\n            NoMatches: If no matching child is found.\n\n        Returns:\n            The first immediate child widget with the expected type.\n        \"\"\"","sourceCodeStart":1131,"sourceCodeEnd":1167,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/widget.py#L1131-L1167","documentation":"Deep lookup variant: get_widget_by_id uses query_one('#id') and then checks expect_type; WrongType signals the descendant exists but is not the expected type.","triggerScenarios":"get_widget_by_id(\"footer\", expect_type=Footer) where a different widget type holds that id somewhere in the subtree.","commonSituations":"Reusing an id across different screens/layouts after refactors; custom replacements for stock widgets keeping the same id.","solutions":["Align expect_type with the actual widget type","Rename ids so each type has a distinct id","Use query_one with a compound selector like \"#footer.footer-class\""],"exampleFix":"# before\nw = self.get_widget_by_id(\"footer\", expect_type=Footer)\n# after\nw = self.get_widget_by_id(\"footer\", expect_type=MyCustomFooter)","handlingStrategy":"type-guard","validationCode":"widget = self.query_one(f\"#{id}\")\nif isinstance(widget, expect_type):\n    use(widget)","typeGuard":"def descendant_is_type(root: Widget, id: str, t: type) -> bool:\n    return isinstance(root.query_one(f\"#{id}\"), t)","tryCatchPattern":"try:\n    w = self.get_widget_by_id(\"x\", expect_type=T)\nexcept WrongType:\n    w = self.query_one(\"#x\")  # handle actual type","preventionTips":["Give distinct ids per widget type","Keep selectors and widget classes aligned during refactors"],"tags":["dom-tree","type-mismatch","query","textual"],"backgroundTag":"wrong-element-type","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}