{"record":{"id":"65f68983935fab19","repo":"Textualize/textual","slug":"unable-to-bind-non-reactive-attribute-name-r-on","errorCode":null,"errorMessage":"Unable to bind non-reactive attribute {name!r} on {self}","messagePattern":"Unable to bind non-reactive attribute (.+?) on (.+?)","errorType":"exception","errorClass":"ReactiveError","httpStatus":null,"severity":"error","filePath":"src/textual/dom.py","lineNumber":335,"sourceCode":"                yield WorldClock(\"Asia/Tokyo\").data_bind(WorldClockApp.time)\n            ```\n\n        Raises:\n            ReactiveError: If the data wasn't bound.\n\n        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","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/dom.py#L317-L353","documentation":"DOMNode.data_bind raises ReactiveError when binding a name that is not a reactive attribute on self — data binding requires the target (self) to declare a reactive with that name so incoming changes can be stored and watched.","triggerScenarios":"widget.data_bind(SomeApp.field) where the widget has no reactive named 'field'; binding to a plain attribute or property; binding to a reactive defined only on the parent/app, not on the binding widget.","commonSituations":"Using @on/data_bind for app-to-widget sync but forgetting to declare the matching reactive on the widget; renaming the app reactive without updating widget declarations.","solutions":["Declare a reactive with the same name on the binding widget: count: reactive[int] = reactive(0)","Or bind to a different mechanism (e.g. watch methods / messages) if the widget shouldn't own state","Ensure names match exactly between the parent reactive and the widget reactive"],"exampleFix":"# before\nclass MyWidget(Widget):\n    def compose(self):\n        yield Label().data_bind(MyApp.status)  # no 'status' reactive on Label\n# after\nclass MyWidget(Widget):\n    status: reactive[str] = reactive(\"\")\n    def compose(self):\n        yield Label().data_bind(MyWidget.status)","handlingStrategy":"validation","validationCode":"class MyWidget(Widget):\n    status: reactive[str] = reactive(\"\")  # declare before data_bind(MyApp.status)","typeGuard":"from textual.reactive import reactive\n\ndef can_bind(node, name: str) -> bool:\n    return name in node._reactives","tryCatchPattern":"from textual.reactive import ReactiveError\ntry:\n    child.data_bind(MyApp.status)\nexcept ReactiveError as e:\n    log.warning(str(e))","preventionTips":["Declare a matching reactive on the binding widget for every data_bind name","Keep parent and widget reactive names in sync when renaming","Type-check binding targets in tests"],"tags":["textual","reactive","data-binding","dom"],"backgroundTag":"binding-target-missing","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}