{"record":{"id":"13849c9f9b4bfc77","repo":"Textualize/rich","slug":"original-color-r-is-not-a-valid-color","errorCode":null,"errorMessage":"{original_color!r} is not a valid color","messagePattern":"(.+?) is not a valid color","errorType":"validation","errorClass":"ColorParseError","httpStatus":null,"severity":"error","filePath":"rich/color.py","lineNumber":451,"sourceCode":"    def parse(cls, color: str) -> \"Color\":\n        \"\"\"Parse a color definition.\"\"\"\n        original_color = color\n        color = color.lower().strip()\n\n        if color == \"default\":\n            return cls(color, type=ColorType.DEFAULT)\n\n        color_number = ANSI_COLOR_NAMES.get(color)\n        if color_number is not None:\n            return cls(\n                color,\n                type=(ColorType.STANDARD if color_number < 16 else ColorType.EIGHT_BIT),\n                number=color_number,\n            )\n\n        color_match = RE_COLOR.match(color)\n        if color_match is None:\n            raise ColorParseError(f\"{original_color!r} is not a valid color\")\n\n        color_24, color_8, color_rgb = color_match.groups()\n        if color_24:\n            triplet = ColorTriplet(\n                int(color_24[0:2], 16), int(color_24[2:4], 16), int(color_24[4:6], 16)\n            )\n            return cls(color, ColorType.TRUECOLOR, triplet=triplet)\n\n        elif color_8:\n            number = int(color_8)\n            if number > 255:\n                raise ColorParseError(f\"color number must be <= 255 in {color!r}\")\n            return cls(\n                color,\n                type=(ColorType.STANDARD if number < 16 else ColorType.EIGHT_BIT),\n                number=number,\n            )\n","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/Textualize/rich/blob/9d8f9a372cc5916fd4781fec207ced7ddac2f08f/rich/color.py#L433-L469","documentation":"Color.parse (via the Color classmethod used for every color string rich handles) raises ColorParseError when the string matches none of the accepted forms: a standard/eight-bit ANSI name (like \"red\" or \"grey42\"), a 6-digit hex like \"#ffcc00\", a bare number 0-255, or \"rgb(r,g,b)\". The regex RE_COLOR rejects the string after the ANSI name lookup fails. This propagates up through Style parsing, so a bad color inside a style string (e.g. \"bold on nosuchcolor\") surfaces as this error (often wrapped in StyleSyntaxError).","triggerScenarios":"console.print(\"x\", style=\"bck #ff0000\") with a typo'd color name; Color.parse(\"#ffcc0\") (5 hex digits); Color.parse(\"rgb(300,0,0)\") actually hits a different check, but \"rgb(1 2 3)\" or \"blueish\" hits this one; passing a color from unvalidated user/theme config.","commonSituations":"Typos in color names in theme files or CLI style flags (\"maganta\", \"grean\"); hex strings with missing digits or a missing '#' handled elsewhere; CSS-style 3-digit hex (#fc0) which rich does not support; theme JSON keys pointing at colors from a newer rich version (e.g. \"grey37\" variants) while running an older rich.","solutions":["Fix the color string: use a documented ANSI name (see rich.color.ANSI_COLOR_NAMES), \"#rrggbb\" hex, \"rgb(r,g,b)\", or an integer 0-255","If the color comes from user/theme config, validate it once at load time with a try/except ColorParseError and fall back to a default","Check for 3-digit CSS hex (#fc0) and expand it to 6 digits (#ffcc00) before passing to rich","Upgrade rich if the color name is a newer addition (e.g. some greyNN names)"],"exampleFix":"// before (Python)\nColor.parse(\"#fc0\")            # ColorParseError\nconsole.print(\"hi\", style=\"on maganta\")  # ColorParseError\n// after\nColor.parse(\"#ffcc00\")\nconsole.print(\"hi\", style=\"on magenta\")","handlingStrategy":"try-catch","validationCode":"import re\nfrom rich.color import ANSI_COLOR_NAMES, RE_COLOR\n\ndef looks_like_color(s: str) -> bool:\n    return s in ANSI_COLOR_NAMES or RE_COLOR.match(s) is not None","typeGuard":"def is_probably_valid_color(value: str) -> bool:\n    from rich.color import ANSI_COLOR_NAMES, RE_COLOR\n    return value in ANSI_COLOR_NAMES or bool(RE_COLOR.match(value))","tryCatchPattern":"from rich.color import ColorParseError, Color\n\ntry:\n    color = Color.parse(user_color)\nexcept ColorParseError:\n    color = Color.parse(\"default\")  # fallback\n    log.warning(\"unknown color %r, using default\", user_color)","preventionTips":["Validate all theme/config colors once at startup with Color.parse in a try/except","Expand CSS 3-digit hex (#fc0 -> #ffcc00) before handing it to rich","Check rich.color.ANSI_COLOR_NAMES for the exact spelling of named colors","Upgrade rich when using recently added color names"],"tags":["python","rich","color","style","parsing","colorparseerror"],"backgroundTag":null,"analyzedSha":"9d8f9a372cc5916fd4781fec207ced7ddac2f08f","analyzedAt":"2026-08-15T03:30:11.781Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}