{"record":{"id":"ce07ccf2dec5b6a8","repo":"Textualize/textual","slug":"unable-to-bind-data-reactive-owner-name-is","errorCode":null,"errorMessage":"Unable to bind data; {reactive.owner.__name__} is not defined on {parent.__class__.__name__}.","messagePattern":"Unable to bind data; (.+?) is not defined on (.+?)\\.","errorType":"exception","errorClass":"ReactiveError","httpStatus":null,"severity":"error","filePath":"src/textual/dom.py","lineNumber":341,"sourceCode":"        Returns:\n            Self.\n        \"\"\"\n        _rich_traceback_omit = True\n\n        parent = active_message_pump.get()\n\n        if self._reactive_connect is None:\n            self._reactive_connect = {}\n        bind_vars = {**{reactive.name: reactive for reactive in reactives}, **bind_vars}\n        for name, reactive in bind_vars.items():\n            if name not in self._reactives:\n                raise ReactiveError(\n                    f\"Unable to bind non-reactive attribute {name!r} on {self}\"\n                )\n            if isinstance(reactive, Reactive) and not isinstance(\n                parent, reactive.owner\n            ):\n                raise ReactiveError(\n                    f\"Unable to bind data; {reactive.owner.__name__} is not defined on {parent.__class__.__name__}.\"\n                )\n            self._reactive_connect[name] = (parent, reactive)\n        if self._is_mounted:\n            self._initialize_data_bind()\n        else:\n            self.call_later(self._initialize_data_bind)\n        return self\n\n    def _initialize_data_bind(self) -> None:\n        \"\"\"initialize a data binding.\n\n        Args:\n            compose_parent: The node doing the binding.\n        \"\"\"\n        if not self._reactive_connect:\n            return\n        for variable_name, (compose_parent, reactive) in self._reactive_connect.items():","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/dom.py#L323-L359","documentation":"Thrown by DOMNode.data_bind when the reactive attribute being bound was defined on a different owner class than the parent object passed to the bind. Textual verifies that the reactive descriptor's owner (the class where @reactive was declared) matches the parent's class before wiring the connection.","triggerScenarios":"Calling widget.data_bind(parent) or using the `data-bind` CSS pattern where the referenced attribute is a reactive defined on a class other than parent's class (e.g. binding a widget's reactive to a plain object, or to a subclass/superclass that doesn't inherit the reactive's owner).","commonSituations":"Binding to a dataclass or plain Python object instead of a DOMNode with @reactive attributes; refactoring reactives between classes while keeping old data-bind declarations; typos in the attribute name resolving to a similarly-named reactive on another class.","solutions":["Ensure the parent object passed to data_bind is an instance of (or inherits from) the class where the reactive attribute is declared with @reactive","If the parent is a plain object, either make the attribute a textual.reactive on a DOMNode subclass or use watch methods/manual refresh instead of data_bind","Check the `data-bind` selector/attribute path in TSS points at a widget class that actually defines that reactive"],"exampleFix":"# before\nclass MyApp(App):\n    count = reactive(0)\n\nwidget.data_bind(some_plain_obj)  # ReactiveError\n\n# after\nclass MyApp(App):\n    count = reactive(0)\n\nwidget.data_bind(my_app_instance)  # owner matches MyApp","handlingStrategy":"validation","validationCode":"from textual.reactive import Reactive\n\ndef can_bind(parent, attr: str) -> bool:\n    for klass in type(parent).__mro__:\n        reactive = klass.__dict__.get(attr)\n        if isinstance(reactive, Reactive):\n            return isinstance(parent, reactive.owner)\n    return False\n\nassert can_bind(parent_obj, 'count'), 'owner mismatch'","typeGuard":"def has_reactive_owner(parent: object, attr: str) -> bool:\n    return any(\n        isinstance(v, Reactive) and isinstance(parent, v.owner)\n        for k in type(parent).__mro__ for v in vars(k).values()\n        if k is not object\n    ) if hasattr(type(parent), '__mro__') else False","tryCatchPattern":"from textual.reactive import ReactiveError\ntry:\n    widget.data_bind(parent)\nexcept ReactiveError as e:\n    log.warning(f'bind failed: {e}')  # fall back to manual watch/refresh","preventionTips":["Declare reactives on the class that will be the bind parent","Type-hint data_bind parents to the reactive-owning class","Unit-test data bindings against the real parent class"],"tags":["textual","reactive","data-binding","tui"],"backgroundTag":"reactive-binding-owner-mismatch","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}