Textualize/rich · error · ThemeStackError
Unable to pop base theme
Error message
Unable to pop base theme
What it means
ThemeStack keeps a list of pushed theme dicts, always retaining the single base theme as the bottom entry. pop_theme() refuses to pop when len(_entries) == 1 — removing the base would leave the stack with no styles at all — raising ThemeStackError('Unable to pop base theme').
Source
Thrown at rich/theme.py:109
def push_theme(self, theme: Theme, inherit: bool = True) -> None:
"""Push a theme on the top of the stack.
Args:
theme (Theme): A Theme instance.
inherit (boolean, optional): Inherit styles from current top of stack.
"""
styles: Dict[str, Style]
styles = (
{**self._entries[-1], **theme.styles} if inherit else theme.styles.copy()
)
self._entries.append(styles)
self.get = self._entries[-1].get
def pop_theme(self) -> None:
"""Pop (and discard) the top-most theme."""
if len(self._entries) == 1:
raise ThemeStackError("Unable to pop base theme")
self._entries.pop()
self.get = self._entries[-1].get
if __name__ == "__main__": # pragma: no cover
theme = Theme()
print(theme.config)
View on GitHub (pinned to 9d8f9a372c)
Solutions
- Match every pop_theme() with exactly one push_theme(); prefer a try/finally around the themed block.
- Track nesting depth yourself, or guard: pop only if you know you pushed (pass/return a token).
- If you need the base theme back without popping, just push the default theme instead of popping past the base.
Example fix
# before
console.pop_theme() # extra pop -> ThemeStackError
# after
console.push_theme(my_theme)
try:
...
finally:
console.pop_theme() # exactly one pop per push Defensive patterns
Strategy: try-catch
Validate before calling
from rich.theme import ThemeStackError # count pushes if you must pop conditionally pushed = getattr(console, '_thread_pushes', 0) # not exposed; track yourself:
Try / catch
from rich.theme import ThemeStackError
try:
console.pop_theme()
except ThemeStackError:
pass # already at base theme Prevention
- Wrap themed sections in try/finally with exactly one push_theme/pop_theme pair.
- Catch ThemeStackError defensively in cleanup code that might run twice.
- Use a contextmanager helper to guarantee push/pop balance.
When it happens
Trigger: Calling console.pop_theme() more times than push_theme() was called (unbalanced push/pop); popping on a fresh stack that never pushed; an exception path between push_theme and pop_theme that double-pops (e.g. finally-block pop after an early pop).
Common situations: Temporarily applying a theme around a code block (push/pop in try/finally) where a nested routine also pops; context-manager helper that pops in __exit__ being used without a matching enter; copy-paste of the push/pop snippet without the push line.
Related errors
- invalid value for align, expected "left", "center", or "righ
- invalid value for vertical, expected "top", "middle", or "bo
- level must be 'head', 'row' or 'foot'
- {original_color!r} is not a valid color
- color number must be <= 255 in {color!r}
AI-assisted analysis of Textualize/rich@9d8f9a372c (2026-08-15).
Data as JSON: /api/errors/9ffa9720324114e8.
Report an issue: GitHub.