Textualize/textual · error · SignalError
Node must be running to subscribe to a signal (has {node} be
Error message
Node must be running to subscribe to a signal (has {node} been mounted)? What it means
Textual's Signal system only allows live, mounted nodes to subscribe because delivery requires an active message pump. Subscribing a widget before it is running raises SignalError.
Source
Thrown at src/textual/signal.py:78
node: DOMNode,
callback: SignalCallbackType[SignalT],
immediate: bool = False,
) -> None:
"""Subscribe a node to this signal.
When the signal is published, the callback will be invoked.
Args:
node: Node to subscribe.
callback: A callback function which takes a single argument and returns anything (return type ignored).
immediate: Invoke the callback immediately on publish if `True`, otherwise post it to the DOM node to be
called once existing messages have been processed.
Raises:
SignalError: Raised when subscribing a non-mounted widget.
"""
if not node.is_running:
raise SignalError(
f"Node must be running to subscribe to a signal (has {node} been mounted)?"
)
if immediate:
def signal_callback(data: SignalT) -> None:
"""Invoke the callback immediately."""
callback(data)
else:
def signal_callback(data: SignalT) -> None:
"""Post the callback to the node, to call at the next opertunity."""
node.call_next(callback, data)
callbacks = self._subscriptions.setdefault(node, [])
callbacks.append(signal_callback)
View on GitHub (pinned to 06dbeef4bb)
Solutions
- Move subscribe() calls into on_mount (or the _on_mount handler)
- If subscribing another node, verify node.is_running first
- Unsubscribe in on_unmount to avoid leaks
Example fix
# before
class MyWidget(Widget):
def __init__(self):
super().__init__()
MY_SIGNAL.subscribe(self, self.on_signal) # not mounted yet
# after
class MyWidget(Widget):
def on_mount(self) -> None:
MY_SIGNAL.subscribe(self, self.on_signal) Defensive patterns
Strategy: validation
Validate before calling
if node.is_running:
SIGNAL.subscribe(node, callback) Try / catch
from textual.signal import SignalError
try:
SIGNAL.subscribe(self, self.on_signal)
except SignalError:
self.call_after_refresh(lambda: SIGNAL.subscribe(self, self.on_signal)) Prevention
- Subscribe only in on_mount
- Unsubscribe in on_unmount
When it happens
Trigger: Calling signal.subscribe(node) in __init__, on the class, or in a handler that runs before mount; also subscribing an already-unmounted node.
Common situations: Wiring subscriptions in a widget constructor instead of on_mount; subscribing widgets created but never mounted; subscribing after removal from the DOM.
Related errors
- Can't animate attribute {attribute!r} on {obj!r}; attribute
- Don't know how to animate {value!r}; Can only animate <int>,
- Can't encode {datum!r}
- must be bytes
- More data expected
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/2fd8847d96b0906b.
Report an issue: GitHub.