python/cpython · error · ValueError

Expected Theme object, found {t}

Error message

Expected Theme object, found {t}

What it means

ValueError raised by _colorize.set_theme() (Lib/_colorize.py) when the argument is not an instance of the internal _colorize.Theme class. set_theme is the single hook for replacing the interpreter's color theme; it deliberately rejects dicts, strings, and third-party look-alikes so that THEME_TOKEN-based rendering never receives an unknown object.

Source

Thrown at Lib/_colorize.py:643

    See `Theme.no_colors()` for more information.

    It is recommended not to cache the result of this function for extended
    periods of time because the user might influence theme selection by
    the interactive shell, a debugger, or application-specific code. The
    environment (including environment variable state and console configuration
    on Windows) can also change in the course of the application life cycle.
    """
    if force_color or (not force_no_color and
                       can_colorize(file=tty_file)):
        return _theme
    return theme_no_color


def set_theme(t: Theme) -> None:
    global _theme

    if not isinstance(t, Theme):
        raise ValueError(f"Expected Theme object, found {t}")

    _theme = t


set_theme(default_theme)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass an actual _colorize.Theme: t = _colorize.themes['neutral']; _colorize.set_theme(t) (or a copy you mutate via Theme construction), not a dict.
  2. To tweak, start from an existing Theme and construct a new Theme with modified token rules rather than a plain mapping.
  3. If you only want colors on/off, use environment controls (PYTHON_COLORS=0/1, NO_COLOR, FORCE_COLOR) or initialize(...) flags instead of swapping themes.
  4. Register custom themes at startup via the documented theme hook (e.g. PYTHON_COLORS_THEME / user theme registration) rather than ad-hoc objects.

Example fix

# before
import _colorize
_colorize.set_theme({'subject': {'fg': 'green'}})  # ValueError: Expected Theme object

# after
import _colorize
theme = _colorize.themes['neutral']
_colorize.set_theme(theme)  # a real Theme instance
Defensive patterns

Strategy: type-guard

Validate before calling

import _colorize

def theme_ok(t) -> bool:
    return isinstance(t, _colorize.Theme)

Type guard

import _colorize

def is_theme(t) -> bool:
    """Type guard: True only for real _colorize Theme instances."""
    return isinstance(t, _colorize.Theme)

Try / catch

try:
    _colorize.set_theme(candidate)
except ValueError as e:
    if 'Expected Theme object' in str(e):
        _colorize.set_theme(_colorize.themes['neutral'])  # known-good Theme
    else:
        raise

Prevention

When it happens

Trigger: Calling _colorize.set_theme({'subject': {'fg': 'blue'}}) or set_theme('monokai') — anything that is not a Theme instance. Also wrapping or copying themes: a subclass of Theme is accepted, but duck-typed objects are not.

Common situations: Users trying to customize PYTHON_COLORS_REPL/theme output by poking at _colorize; scripts copying a theme dict out of _colorize.themes and feeding it back; third-party REPL/tools integrating CPython's colorizer and assuming a mapping API.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/82dd1f34fe85078c. Report an issue: GitHub.