{"record":{"id":"2728f8e614db6705","repo":"3b1b/manim","slug":"unsupported-path-verb","errorCode":null,"errorMessage":"Unsupported: {path_verb}","messagePattern":"Unsupported: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"manimlib/mobject/boolean_ops.py","lineNumber":48,"sourceCode":"    PathVerb = pathops.PathVerb\r\n    current_path_start = np.array([0.0, 0.0, 0.0])\r\n    for path_verb, points in path:\r\n        if path_verb == PathVerb.CLOSE:\r\n            vmobject.add_line_to(current_path_start)\r\n        else:\r\n            points = np.hstack((np.array(points), np.zeros((len(points), 1))))\r\n            if path_verb == PathVerb.MOVE:\r\n                for point in points:\r\n                    current_path_start = point\r\n                    vmobject.start_new_path(point)\r\n            elif path_verb == PathVerb.CUBIC:\r\n                vmobject.add_cubic_bezier_curve_to(*points)\r\n            elif path_verb == PathVerb.LINE:\r\n                vmobject.add_line_to(points[0])\r\n            elif path_verb == PathVerb.QUAD:\r\n                vmobject.add_quadratic_bezier_curve_to(*points)\r\n            else:\r\n                raise Exception(f\"Unsupported: {path_verb}\")\r\n    return vmobject.reverse_points()\r\n\r\n\r\nclass Union(VMobject):\r\n    def __init__(self, *vmobjects: VMobject, **kwargs):\r\n        if len(vmobjects) < 2:\r\n            raise ValueError(\"At least 2 mobjects needed for Union.\")\r\n        super().__init__(**kwargs)\r\n        outpen = pathops.Path()\r\n        paths = [\r\n            _convert_vmobject_to_skia_path(vmobject)\r\n            for vmobject in vmobjects\r\n        ]\r\n        pathops.union(paths, outpen.getPen())\r\n        _convert_skia_path_to_vmobject(outpen, self)\r\n\r\n\r\nclass Difference(VMobject):\r","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/mobject/boolean_ops.py#L30-L66","documentation":"Raised while converting a Skia path back into a VMobject after a boolean operation (Union/Difference/Intersection/Exclusion) in manimlib/mobject/boolean_ops.py. The converter handles only the PathVerbs MOVE, CUBIC, LINE, and QUAD; any other verb in the skia-pathops result (CLOSE, and especially CONIC) hits the else branch. CONIC segments typically appear when a source path contains arcs, circles, or rounded corners, because skia-pathops represents circular arcs as conics.","triggerScenarios":"Calling Union/Difference/Intersection/Exclusion on VMobjects whose converted skia path (or whose boolean-op RESULT path) contains a PathVerb other than MOVE/CUBIC/LINE/QUAD, e.g. Circle, Arc, AnnularSector, or any mobject whose points come from SVG paths with arc commands. The result path itself can gain a CONIC even if inputs had none.","commonSituations":"Using boolean ops on Arc/Circle/CubicBezier-vs-arc shapes; importing SVGs with arc commands and feeding them to boolean ops; upgrading skia-pathops versions where op results preserve conics; building custom VMobjects via append_quadratic_bezier_curve or arc points.","solutions":["Replace arc-based shapes with polygonal/pure-cubic approximations (e.g. use a Polygon with many sides, or set_arc_points equivalents that emit CUBIC) before the boolean op","Pre-process the skia path: iterate pathops.Path and call pathops verbs to convert/drop CONIC/CLOSE verbs before _convert_skia_path_to_vmobject runs (monkey-patch or copy the private function)","Wrap the boolean op in try/except and fall back to manual path construction without pathops","Check skia-pathops version compatibility; some versions emit CLOSE verbs that this manim build does not filter"],"exampleFix":"# before\nshape = Union(Circle(), Square())  # may raise: Unsupported: PathVerb.CONIC\n\n# after\nfrom manimlib import Circle, Square, Polygon, Union\ncirc = Polygon(*Circle().get_anchors(), fill_in_scene=False)  # cubic-only approximation\nshape = Union(circ, Square())","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = Union(mob_a, mob_b)\nexcept Exception as e:\n    if \"Unsupported\" in str(e):\n        # conic/close verb in skia result; fall back to non-boolean construction\n        result = VGroup(mob_a, mob_b)\n    else:\n        raise","preventionTips":["Avoid boolean ops on arc-based shapes (Circle, Arc, rounded SVG paths); approximate with cubic-only polygons first","Pin a known-good skia-pathops version and test boolean ops over all shape types after upgrades","Wrap scene-level boolean calls in a helper that catches the unsupported-verb error and degrades gracefully"],"tags":["manim","boolean-ops","skia-pathops","geometry"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}