nautechsystems/nautilus_trader · error · ValueError

Colors dict missing required keys: {missing_keys}. Required

Error message

Colors dict missing required keys: {missing_keys}. Required keys: {required_keys}

What it means

register_theme requires the colors dict to contain all six semantic keys — primary, positive, negative, neutral, background, grid — because the tearsheet renderers dereference exactly these slots. Missing any subset raises ValueError naming the missing keys and the full required set; extra keys are tolerated.

Source

Thrown at python/nautilus_trader/analysis/themes.py:178

    ...         "negative": "#ff0000",
    ...         "neutral": "#808080",
    ...         "background": "#ffffff",
    ...         "grid": "#dddddd",
    ...     },
    ... )

    """
    _require_not_none(name, "name")
    _require_not_none(template, "template")
    _require_not_none(colors, "colors")

    if not name.strip():
        raise ValueError("Theme name cannot be empty")

    required_keys = {"primary", "positive", "negative", "neutral", "background", "grid"}
    missing_keys = required_keys - set(colors.keys())
    if missing_keys:
        raise ValueError(
            f"Colors dict missing required keys: {missing_keys}. Required keys: {required_keys}",
        )

    _THEMES[name] = {
        "template": template,
        "colors": colors.copy(),
    }


def list_themes() -> list[str]:
    """
    List all registered theme names.

    Returns
    -------
    list[str]
        List of available theme names.

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Add the missing keys listed in the error, choosing sensible hex values for each semantic role
  2. Start from a built-in theme and override: base = get_theme('plotly_white')['colors']; base.update(my_overrides); register_theme(..., base)

Example fix

# before
register_theme('corp', 'plotly_white', {'primary': '#1f77b4', 'positive': '#2ca02c', 'negative': '#d62728', 'neutral': '#808080', 'background': '#ffffff'})
# ValueError: Colors dict missing required keys: {'grid'}

# after
register_theme('corp', 'plotly_white', {'primary': '#1f77b4', 'positive': '#2ca02c', 'negative': '#d62728', 'neutral': '#808080', 'background': '#ffffff', 'grid': '#dddddd'})
Defensive patterns

Strategy: validation

Validate before calling

REQUIRED = {'primary', 'positive', 'negative', 'neutral', 'background', 'grid'}
missing = REQUIRED - set(colors)
if missing:
    raise ValueError(f'Add color entries for: {missing}')
register_theme(name, template, colors)

Type guard

REQUIRED = {'primary', 'positive', 'negative', 'neutral', 'background', 'grid'}

def is_complete_palette(colors: object) -> bool:
    return isinstance(colors, dict) and REQUIRED <= set(colors)

Prevention

When it happens

Trigger: register_theme('x', 'plotly_white', {'primary': '#1f77b4', 'positive': '#2ca02c'}) — negative/neutral/background/grid absent; also partial updates built by copying an incomplete example.

Common situations: Porting a corporate palette that lacks an obvious 'grid' or 'neutral' color; trimming a theme dict and accidentally dropping a key; dict built from a config that only overrides two colors.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/6803ba01e55dbf38. Report an issue: GitHub.