Textualize/textual · error · RemoveRootError
Attempt to remove the root node of a Tree.
Error message
Attempt to remove the root node of a Tree.
What it means
RemoveRootError from TreeNode.remove(): the Tree widget's root node is structural and cannot be removed; removing it would leave the widget in an invalid state. Use root.remove_children() to empty the tree instead.
Source
Thrown at src/textual/widgets/_tree.py:501
"""Remove the current node and all its children.
Note:
This is the internal support method for `remove`. Call `remove`
to ensure the tree gets refreshed.
"""
self._remove_children()
assert self._parent is not None
del self._parent._children[self._parent._children.index(self)]
del self._tree._tree_nodes[self.id]
def remove(self) -> None:
"""Remove this node from the tree.
Raises:
RemoveRootError: If there is an attempt to remove the root.
"""
if self.is_root:
raise RemoveRootError("Attempt to remove the root node of a Tree.")
self._remove()
self._tree._invalidate()
def remove_children(self) -> None:
"""Remove any child nodes of this node."""
self._remove_children()
self._tree._invalidate()
def refresh(self) -> None:
"""Initiate a refresh (repaint) of this node."""
self._updates += 1
self._tree._refresh_line(self._line)
class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""A widget for displaying and navigating data in a tree."""
ICON_NODE = "▶ "View on GitHub (pinned to 06dbeef4bb)
Solutions
- Use `tree.clear()` to reset the whole tree.
- Use `tree.root.remove_children()` to keep the root but delete contents.
- Guard loops with `if not node.is_root: node.remove()`.
Example fix
# before tree.root.remove() # after tree.clear() # or tree.root.remove_children()
Defensive patterns
Strategy: validation
Validate before calling
if node.is_root:
tree.clear()
else:
node.remove() Type guard
from textual.widgets._tree import TreeNode
def is_removable(n: TreeNode) -> bool:
return not n.is_root Try / catch
from textual.widgets._tree import RemoveRootError
try:
node.remove()
except RemoveRootError:
tree.clear() Prevention
- Use tree.clear() to empty trees
- Filter root in bulk-deletion loops: [n.remove() for n in nodes if not n.is_root]
When it happens
Trigger: Calling `tree.root.remove()` directly, or iterating `tree.iter_expanded_nodes()`/walk and calling remove() without excluding the root.
Common situations: Generic deletion loops that call `.remove()` on every node; attempting to clear the tree by removing root instead of `tree.clear()`.
Related errors
- Unable to remove; there is no option at index {index}
- Unable to add a node both before and after a node
- The node specified for `before` is not a child of this node
- `before` argument must be an index or a TreeNode object to a
- The node specified for `after` is not a child of this node
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/2d724946f6e7279f.
Report an issue: GitHub.