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
- Add the missing keys listed in the error, choosing sensible hex values for each semantic role
- 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
- Derive custom palettes from a built-in: base = get_theme('plotly_white')['colors']; base.update(overrides)
- Keep the six required keys in a shared constant and reuse it in tests
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
- Theme name cannot be empty
- {name} must not be None
- Theme '{name}' not found.{suggestion_text} Available themes:
- No tearsheet chart registered under '{chart_name}'.{hint} Re
- Chart renderer must be callable, was {type(renderer)}
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/6803ba01e55dbf38.
Report an issue: GitHub.