{"record":{"id":"d9aa68629c677794","repo":"roboflow/supervision","slug":"invalid-characters-in-color-hash","errorCode":null,"errorMessage":"Invalid characters in color hash","messagePattern":"Invalid characters in color hash","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/draw/color.py","lineNumber":58,"sourceCode":"    \"#46F0F0\",\n    \"#F032E6\",\n    \"#D2F53C\",\n    \"#FABEBE\",\n    \"#008080\",\n    \"#E6BEFF\",\n    \"#AA6E28\",\n    \"#FFFAC8\",\n    \"#800000\",\n    \"#AAFFC3\",\n]\n\nROBOFLOW_COLOR_PALETTE = [\"C28DFC\", \"A351FB\", \"8315F9\", \"6706CE\", \"5905B3\", \"4D049A\"]\n\n\ndef _validate_color_hex(color_hex: str) -> None:\n    color_hex = color_hex.lstrip(\"#\")\n    if not all(c in \"0123456789abcdefABCDEF\" for c in color_hex):\n        raise ValueError(\"Invalid characters in color hash\")\n    if len(color_hex) not in (3, 4, 6, 8):\n        raise ValueError(\"Invalid length of color hash\")\n\n\n@dataclass\nclass Color:\n    \"\"\"\n    Represents a color in RGBA format.\n\n    This class provides methods to work with colors, including creating colors from hex\n    codes, converting colors to hex strings, RGB tuples, BGR tuples, RGBA tuples,\n    and BGRA tuples.\n\n    Attributes:\n        r: Red channel value (0-255).\n        g: Green channel value (0-255).\n        b: Blue channel value (0-255).\n        a: Alpha channel value (0-255). Default is 255 (fully opaque).","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/draw/color.py#L40-L76","documentation":"Raised by _validate_color_hex when a hex color string contains characters outside [0-9a-fA-F] after stripping an optional leading '#'. All Color.from_hex_color() / palette parsing goes through this validator. It guards the subsequent length check (3/4/6/8 digits) and the int(hex, 16) parse from garbage input like 'GGG' or '#12G45F'.","triggerScenarios":"Calling Color.from_hex_color('xyz123'), passing a CSS rgb() string, including the '#' twice ('##ff0000' — the second '#' fails the character test), or typos like '#ff00gg'.","commonSituations":"User-supplied theme colors from a config/UI field without validation; colors copied with stray characters; abbreviations like 'rgb(255,0,0)' or named colors ('red') passed where hex is expected.","solutions":["Normalize input before use: strip whitespace, allow only one leading '#', then validate with a regex like ^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$","Convert named/CSS colors to hex first (e.g. matplotlib.colors.to_hex)","Pre-validate UI color pickers to emit hex only"],"exampleFix":"# before\ncolor = Color.from_hex_color('#ff00gg')  # 'g' is not a hex digit\n\n# after\nimport re\n\nif not re.fullmatch(r'#?[0-9a-fA-F]{3,4}|#?[0-9a-fA-F]{6}|#?[0-9a-fA-F]{8}', value):\n    raise ValueError(f'Not a hex color: {value!r}')\ncolor = Color.from_hex_color(value.lower())","handlingStrategy":"validation","validationCode":"import re\n\nHEX_RE = re.compile(r'^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$')\n\ndef normalize_hex(value: str) -> str:\n    value = value.strip()\n    if not HEX_RE.fullmatch(value):\n        raise ValueError(f'not a hex color: {value!r}')\n    return value\n\ncolor = Color.from_hex_color(normalize_hex(user_input))","typeGuard":"import re\n\nHEX_COLOR_RE = re.compile(r'#?(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})')\n\ndef is_hex_color(value: object) -> bool:\n    \"\"\"True when value is a valid 3/4/6/8-digit hex color string.\"\"\"\n    return isinstance(value, str) and HEX_COLOR_RE.fullmatch(value) is not None","tryCatchPattern":"try:\n    color = Color.from_hex_color(theme_color)\nexcept ValueError as e:\n    if 'color hash' in str(e):\n        color = Color.WHITE  # safe default, log the bad value\n    else:\n        raise","preventionTips":["Constrain color pickers and config schemas to hex strings","Convert named/CSS colors with matplotlib.colors.to_hex before passing to supervision"],"tags":["color","validation","hex","drawing"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}