{"record":{"id":"8e4872013e458103","repo":"Textualize/textual","slug":"a-reactive-class-is-required-for-example-myapp-t","errorCode":null,"errorMessage":"A Reactive class is required; for example: MyApp.theme","messagePattern":"A Reactive class is required; for example: MyApp\\.theme","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/textual/dom.py","lineNumber":268,"sourceCode":"        self, reactive: Reactive[ReactiveType], value: ReactiveType\n    ) -> None:\n        \"\"\"Sets a reactive value *without* invoking validators or watchers.\n\n        Example:\n            ```python\n            self.set_reactive(App.theme, \"textual-light\")\n            ```\n\n        Args:\n            reactive: A reactive property (use the class scope syntax, i.e. `MyClass.my_reactive`).\n            value: New value of reactive.\n\n        Raises:\n            AttributeError: If the first argument is not a reactive.\n        \"\"\"\n        name = reactive.name\n        if not isinstance(reactive, Reactive):\n            raise TypeError(\"A Reactive class is required; for example: MyApp.theme\")\n        if name not in self._reactives:\n            raise AttributeError(\n                f\"No reactive called {name!r}; Have you called super().__init__(...) in the {self.__class__.__name__} constructor?\"\n            )\n        setattr(self, f\"_reactive_{name}\", value)\n\n    def mutate_reactive(self, reactive: Reactive[ReactiveType]) -> None:\n        \"\"\"Force an update to a mutable reactive.\n\n        Example:\n            ```python\n            self.reactive_name_list.append(\"Jessica\")\n            self.mutate_reactive(MyClass.reactive_name_list)\n            ```\n\n        Textual will automatically detect when a reactive is set to a new value, but it is unable\n        to detect if a value is _mutated_ (such as updating a list, dict, or attribute of an object).\n        If you do wish to use a collection or other mutable object in a reactive, then you can call","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/dom.py#L250-L286","documentation":"DOMNode.set_reactive raises TypeError when the first argument is not a Reactive descriptor instance — e.g. passing a plain value, string, or the class instead of the reactive attribute object.","triggerScenarios":"set_reactive('theme', 'dark') (name instead of reactive), set_reactive(MyApp.theme) missing the value pairing, or passing a Data object instead of a reactive attribute. Signature is set_reactive(reactive, value) where reactive is e.g. MyApp.theme (a Reactive accessed on the class).","commonSituations":"Misreading the API as name/value setter; passing the instance's current value instead of the descriptor; copy-pasting from watch/inspect code that uses strings.","solutions":["Pass the reactive descriptor itself: self.set_reactive(MyApp.theme, 'dark')","Access it from the class that declares it, not an instance copy","For normal updates, just assign: self.theme = 'dark'"],"exampleFix":"# before\nself.set_reactive('theme', 'dark')\n# after\nself.set_reactive(MyApp.theme, 'dark')\n# or simply\nself.theme = 'dark'","handlingStrategy":"type-guard","validationCode":"from textual.reactive import Reactive\nfrom textual.app import App\nassert isinstance(App.theme, Reactive), 'pass the reactive descriptor, not a name/value'","typeGuard":"from textual.reactive import Reactive\ndef is_reactive(obj: object) -> bool:\n    return isinstance(obj, Reactive)","tryCatchPattern":null,"preventionTips":["Pass the reactive descriptor from the class: self.set_reactive(MyApp.theme, value)","Prefer plain attribute assignment for normal updates","Read set_reactive's signature before scripting it"],"tags":["textual","reactive","dom","typeerror","api-misuse"],"backgroundTag":"wrong-argument-type","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}