{"record":{"id":"6803ba01e55dbf38","repo":"nautechsystems/nautilus_trader","slug":"colors-dict-missing-required-keys-missing-keys","errorCode":null,"errorMessage":"Colors dict missing required keys: {missing_keys}. Required keys: {required_keys}","messagePattern":"Colors dict missing required keys: (.+?)\\. Required keys: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/nautilus_trader/analysis/themes.py","lineNumber":178,"sourceCode":"    ...         \"negative\": \"#ff0000\",\n    ...         \"neutral\": \"#808080\",\n    ...         \"background\": \"#ffffff\",\n    ...         \"grid\": \"#dddddd\",\n    ...     },\n    ... )\n\n    \"\"\"\n    _require_not_none(name, \"name\")\n    _require_not_none(template, \"template\")\n    _require_not_none(colors, \"colors\")\n\n    if not name.strip():\n        raise ValueError(\"Theme name cannot be empty\")\n\n    required_keys = {\"primary\", \"positive\", \"negative\", \"neutral\", \"background\", \"grid\"}\n    missing_keys = required_keys - set(colors.keys())\n    if missing_keys:\n        raise ValueError(\n            f\"Colors dict missing required keys: {missing_keys}. Required keys: {required_keys}\",\n        )\n\n    _THEMES[name] = {\n        \"template\": template,\n        \"colors\": colors.copy(),\n    }\n\n\ndef list_themes() -> list[str]:\n    \"\"\"\n    List all registered theme names.\n\n    Returns\n    -------\n    list[str]\n        List of available theme names.\n","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/python/nautilus_trader/analysis/themes.py#L160-L196","documentation":"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.","triggerScenarios":"register_theme('x', 'plotly_white', {'primary': '#1f77b4', 'positive': '#2ca02c'}) — negative/neutral/background/grid absent; also partial updates built by copying an incomplete example.","commonSituations":"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.","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)"],"exampleFix":"# before\nregister_theme('corp', 'plotly_white', {'primary': '#1f77b4', 'positive': '#2ca02c', 'negative': '#d62728', 'neutral': '#808080', 'background': '#ffffff'})\n# ValueError: Colors dict missing required keys: {'grid'}\n\n# after\nregister_theme('corp', 'plotly_white', {'primary': '#1f77b4', 'positive': '#2ca02c', 'negative': '#d62728', 'neutral': '#808080', 'background': '#ffffff', 'grid': '#dddddd'})","handlingStrategy":"validation","validationCode":"REQUIRED = {'primary', 'positive', 'negative', 'neutral', 'background', 'grid'}\nmissing = REQUIRED - set(colors)\nif missing:\n    raise ValueError(f'Add color entries for: {missing}')\nregister_theme(name, template, colors)","typeGuard":"REQUIRED = {'primary', 'positive', 'negative', 'neutral', 'background', 'grid'}\n\ndef is_complete_palette(colors: object) -> bool:\n    return isinstance(colors, dict) and REQUIRED <= set(colors)","tryCatchPattern":null,"preventionTips":["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"],"tags":["python","themes","schema-validation","colors","register-theme"],"backgroundTag":"schema-validation-failed","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}