Textualize/textual · error · TypeError
A Reactive class is required; for example: MyApp.theme
Error message
A Reactive class is required; for example: MyApp.theme
What it means
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.
Source
Thrown at src/textual/dom.py:268
self, reactive: Reactive[ReactiveType], value: ReactiveType
) -> None:
"""Sets a reactive value *without* invoking validators or watchers.
Example:
```python
self.set_reactive(App.theme, "textual-light")
```
Args:
reactive: A reactive property (use the class scope syntax, i.e. `MyClass.my_reactive`).
value: New value of reactive.
Raises:
AttributeError: If the first argument is not a reactive.
"""
name = reactive.name
if not isinstance(reactive, Reactive):
raise TypeError("A Reactive class is required; for example: MyApp.theme")
if name not in self._reactives:
raise AttributeError(
f"No reactive called {name!r}; Have you called super().__init__(...) in the {self.__class__.__name__} constructor?"
)
setattr(self, f"_reactive_{name}", value)
def mutate_reactive(self, reactive: Reactive[ReactiveType]) -> None:
"""Force an update to a mutable reactive.
Example:
```python
self.reactive_name_list.append("Jessica")
self.mutate_reactive(MyClass.reactive_name_list)
```
Textual will automatically detect when a reactive is set to a new value, but it is unable
to detect if a value is _mutated_ (such as updating a list, dict, or attribute of an object).
If you do wish to use a collection or other mutable object in a reactive, then you can callView on GitHub (pinned to 06dbeef4bb)
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'
Example fix
# before
self.set_reactive('theme', 'dark')
# after
self.set_reactive(MyApp.theme, 'dark')
# or simply
self.theme = 'dark' Defensive patterns
Strategy: type-guard
Validate before calling
from textual.reactive import Reactive from textual.app import App assert isinstance(App.theme, Reactive), 'pass the reactive descriptor, not a name/value'
Type guard
from textual.reactive import Reactive
def is_reactive(obj: object) -> bool:
return isinstance(obj, Reactive) Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Unable to bind non-reactive attribute {name!r} on {self}
- expected a callable or string, got {screen_object!r}
- MODES cannot contain instances, use a type instead (got inst
- add_mode() must be called with a Screen type, not an instanc
- No nodes match {self!r} on {self.node!r}
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/8e4872013e458103.
Report an issue: GitHub.