langchain-ai/deepagents · error · ValueError

ThemeEntry.label must be a non-empty string

Error message

ThemeEntry.label must be a non-empty string

What it means

ThemeEntry.label must contain at least one non-whitespace character; __post_init__ rejects empty or whitespace-only labels with ValueError. Labels are shown in the theme picker, so blank labels would render unusable UI rows.

Source

Thrown at libs/code/deepagents_code/theme.py:439

    colors: ThemeColors
    """Resolved color set."""

    custom: bool = True
    """Whether this theme must be registered with Textual via `register_theme()`.

    `True` for LangChain-branded themes and user-defined themes.
    `False` for Textual built-in themes that Textual already knows about.
    """

    def __post_init__(self) -> None:
        """Validate that the label is a non-empty string.

        Raises:
            ValueError: If `label` is empty or whitespace-only.
        """
        if not self.label.strip():
            msg = "ThemeEntry.label must be a non-empty string"
            raise ValueError(msg)


# Curated labels for Textual built-in themes. Themes not listed here fall back
# to a humanized version of the slug (e.g. `ansi-dark` → `Ansi Dark`), so newly
# shipped Textual themes appear in the picker without code changes.
_TEXTUAL_THEME_LABELS: Mapping[str, str] = MappingProxyType(
    {
        "textual-dark": "Textual Dark",
        "textual-light": "Textual Light",
        "ansi-dark": "Terminal ANSI Dark",
        "ansi-light": "Terminal ANSI Light",
        "catppuccin-frappe": "Catppuccin Frappé",
        "rose-pine": "Rosé Pine",
        "rose-pine-dawn": "Rosé Pine Dawn",
        "rose-pine-moon": "Rosé Pine Moon",
        "tokyo-night": "Tokyo Night",
    }
)

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Provide a non-empty label string when constructing ThemeEntry.
  2. If the label may be absent, fall back to a humanized slug (e.g. 'ansi-dark' -> 'Ansi Dark') before construction.
  3. Trim user input and check `label.strip()` before building the entry.

Example fix

// before
ThemeEntry(slug="solarized", label="")
// after
ThemeEntry(slug="solarized", label="Solarized")
Defensive patterns

Strategy: validation

Validate before calling

label = raw_label.strip() or humanize(slug)
if not label:
    raise ValueError("theme label required")
entry = ThemeEntry(slug=slug, label=label)

Type guard

def has_label(label: object) -> TypeGuard[str]:
    return isinstance(label, str) and bool(label.strip())

Try / catch

try:
    entry = ThemeEntry(slug=slug, label=raw_label)
except ValueError:
    entry = ThemeEntry(slug=slug, label=humanize(slug))

Prevention

When it happens

Trigger: Creating ThemeEntry(label="") or ThemeEntry(label=" "), or deserializing a theme entry from config where the label key is missing/blank.

Common situations: Empty string defaults in hand-written theme files, YAML/TOML entries with `label = ""`, or code that derives labels from an empty user-supplied name.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/2e0497128fcb6b83. Report an issue: GitHub.