{"record":{"id":"8a472a8f6b8262ad","repo":"3b1b/manim","slug":"invalid-color-type","errorCode":null,"errorMessage":"Invalid color type","messagePattern":"Invalid color type","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"manimlib/utils/color.py","lineNumber":28,"sourceCode":"from manimlib.constants import COLORMAP_3B1B\nfrom manimlib.constants import WHITE\nfrom manimlib.utils.bezier import interpolate\nfrom manimlib.utils.iterables import resize_with_interpolation\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from typing import Iterable, Sequence, Callable\n    from manimlib.typing import ManimColor, Vect3, Vect4, Vect3Array, Vect4Array, NDArray\n\n\ndef color_to_rgb(color: ManimColor) -> Vect3:\n    if isinstance(color, str):\n        return hex_to_rgb(color)\n    elif isinstance(color, Color):\n        return np.array(color.get_rgb())\n    else:\n        raise Exception(\"Invalid color type\")\n\n\ndef color_to_rgba(color: ManimColor, alpha: float = 1.0) -> Vect4:\n    return np.array([*color_to_rgb(color), alpha])\n\n\ndef rgb_to_color(rgb: Vect3 | Sequence[float]) -> Color:\n    try:\n        return Color(rgb=tuple(rgb))\n    except ValueError:\n        return Color(WHITE)\n\n\ndef rgba_to_color(rgba: Vect4) -> Color:\n    return rgb_to_color(rgba[:3])\n\n\ndef rgb_to_hex(rgb: Vect3 | Sequence[float]) -> str:","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/utils/color.py#L10-L46","documentation":"Raised by color_to_rgb (utils/color.py:28) when the color argument is neither a str (hex name like '#FF0000' or a color name handled by hex_to_rgb) nor a colour.Color instance. Any other type — tuple, list, np.ndarray, int — falls through to the generic error, since only those two representations are understood.","triggerScenarios":"set_fill(color=(1, 0, 0)) or set_color(np.array([0.5, 0.5, 0.5])) raises; passing a QColor, a CSS 'rgb(...)' string, or an int 0xFF0000 also raises. Passing '#FF0000' or Color(rgb=(1,0,0)) works.","commonSituations":"Coming from other graphics libraries where RGB tuples are the norm; storing colors as numpy arrays in scene data; refactors that pass raw values from shaders/interpolations into color APIs.","solutions":["Convert tuples/arrays to a colour.Color first: Color(rgb=tuple(rgb)) — note rgb_to_color does exactly this","Use hex strings ('#RRGGBB') or named colors understood by the colour module","Wrap untrusted color values: color if isinstance(color, (str, Color)) else Color(rgb=tuple(color))"],"exampleFix":"# before\nmob.set_fill(color=(1, 0, 0))  # tuple -> raises\n\n# after\nfrom colour import Color\nmob.set_fill(color=Color(rgb=(1, 0, 0)))","handlingStrategy":"type-guard","validationCode":"from colour import Color\nimport numpy as np\n\ndef as_manim_color(c):\n    if isinstance(c, (str, Color)):\n        return c\n    return Color(rgb=tuple(np.array(c)[:3]))\n\nmob.set_fill(color=as_manim_color(user_color))","typeGuard":"from colour import Color\n\ndef is_manim_color(c) -> bool:\n    return isinstance(c, (str, Color))","tryCatchPattern":null,"preventionTips":["Normalize colors at your API boundary: str hex or Color only","Convert RGB tuples with Color(rgb=tuple(...)) before passing to color APIs","Keep scene color data as hex strings to avoid accidental tuple leakage"],"tags":["manim","color","type-check","validation"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}