{"record":{"id":"074553bebc55601d","repo":"3b1b/manim","slug":"need-at-least-one-color","errorCode":null,"errorMessage":"Need at least one color","messagePattern":"Need at least one color","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"manimlib/mobject/mobject.py","lineNumber":1405,"sourceCode":"    def get_color(self) -> str:\n        return rgb_to_hex(self.data[\"rgba\"][0, :3])\n\n    def get_opacity(self) -> float:\n        return float(self.data[\"rgba\"][0, 3])\n\n    def get_opacities(self) -> float:\n        return self.data[\"rgba\"][:, 3]\n\n    def set_color_by_gradient(self, *colors: ManimColor) -> Self:\n        if self.has_points():\n            self.set_color(colors)\n        else:\n            self.set_submobject_colors_by_gradient(*colors)\n        return self\n\n    def set_submobject_colors_by_gradient(self, *colors: ManimColor, interp_by_hsl=False) -> Self:\n        if len(colors) == 0:\n            raise Exception(\"Need at least one color\")\n        elif len(colors) == 1:\n            return self.set_color(*colors)\n\n        # mobs = self.family_members_with_points()\n        mobs = self.submobjects\n        new_colors = color_gradient(colors, len(mobs), interp_by_hsl=interp_by_hsl)\n\n        for mob, color in zip(mobs, new_colors):\n            mob.set_color(color)\n        return self\n\n    def fade(self, darkness: float = 0.5, recurse: bool = True) -> Self:\n        self.set_opacity(1.0 - darkness, recurse=recurse)\n\n    def get_shading(self) -> np.ndarray:\n        return self.uniforms[\"shading\"]\n\n    def set_shading(","sourceCodeStart":1387,"sourceCodeEnd":1423,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/mobject/mobject.py#L1387-L1423","documentation":"Exception('Need at least one color') raised by Mobject.set_submobject_colors_by_gradient (manimlib/mobject/mobject.py:1405). The method builds a color_gradient(colors, len(mobs)) spread across submobjects; with an empty *colors tuple there is nothing to distribute, so it rejects the call rather than silently leaving submobjects untouched.","triggerScenarios":"Calling set_submobject_colors_by_gradient() with no arguments; passing an empty list splat: mob.set_submobject_colors_by_gradient(*[]); VGroup(...).set_color_by_gradient() when a colors variable evaluated to empty (also routes here when the group has no points).","commonSituations":"Theme/palette code that passes a config-driven color list which ended up empty; filtering colors and splatting the result; typo'd variable names leaving colors undefined-but-defaulted to [].","solutions":["Pass at least one ManimColor: mob.set_submobject_colors_by_gradient(RED, BLUE)","Validate the palette before splatting: assert colors, 'need >= 1 color'","If you meant a no-op recolor, skip the call when the palette is empty instead of calling with zero args"],"exampleFix":"# before\npalette = [c for c in theme if c.is_visible()]\ngroup.set_submobject_colors_by_gradient(*palette)  # raises when palette == []\n\n# after\npalette = [c for c in theme if c.is_visible()]\nif palette:\n    group.set_submobject_colors_by_gradient(*palette)\nelse:\n    group.set_color(WHITE)","handlingStrategy":"validation","validationCode":"assert len(colors) > 0, \"gradient requires at least one color\"\nmob.set_submobject_colors_by_gradient(*colors)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default empty palettes to a single base color before splatting","Validate theme color lists at scene construction, not at call time"],"tags":["manim","mobject","color","gradient","validation"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}