3b1b/manim · error · Exception

Unsupported: {path_verb}

Error message

Unsupported: {path_verb}

What it means

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.

Source

Thrown at manimlib/mobject/boolean_ops.py:48

    PathVerb = pathops.PathVerb
    current_path_start = np.array([0.0, 0.0, 0.0])
    for path_verb, points in path:
        if path_verb == PathVerb.CLOSE:
            vmobject.add_line_to(current_path_start)
        else:
            points = np.hstack((np.array(points), np.zeros((len(points), 1))))
            if path_verb == PathVerb.MOVE:
                for point in points:
                    current_path_start = point
                    vmobject.start_new_path(point)
            elif path_verb == PathVerb.CUBIC:
                vmobject.add_cubic_bezier_curve_to(*points)
            elif path_verb == PathVerb.LINE:
                vmobject.add_line_to(points[0])
            elif path_verb == PathVerb.QUAD:
                vmobject.add_quadratic_bezier_curve_to(*points)
            else:
                raise Exception(f"Unsupported: {path_verb}")
    return vmobject.reverse_points()


class Union(VMobject):
    def __init__(self, *vmobjects: VMobject, **kwargs):
        if len(vmobjects) < 2:
            raise ValueError("At least 2 mobjects needed for Union.")
        super().__init__(**kwargs)
        outpen = pathops.Path()
        paths = [
            _convert_vmobject_to_skia_path(vmobject)
            for vmobject in vmobjects
        ]
        pathops.union(paths, outpen.getPen())
        _convert_skia_path_to_vmobject(outpen, self)


class Difference(VMobject):

View on GitHub (pinned to dee01804d4)

Solutions

  1. 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
  2. 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)
  3. Wrap the boolean op in try/except and fall back to manual path construction without pathops
  4. Check skia-pathops version compatibility; some versions emit CLOSE verbs that this manim build does not filter

Example fix

# before
shape = Union(Circle(), Square())  # may raise: Unsupported: PathVerb.CONIC

# after
from manimlib import Circle, Square, Polygon, Union
circ = Polygon(*Circle().get_anchors(), fill_in_scene=False)  # cubic-only approximation
shape = Union(circ, Square())
Defensive patterns

Strategy: try-catch

Try / catch

try:
    result = Union(mob_a, mob_b)
except Exception as e:
    if "Unsupported" in str(e):
        # conic/close verb in skia result; fall back to non-boolean construction
        result = VGroup(mob_a, mob_b)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of 3b1b/manim@dee01804d4 (2026-08-14). Data as JSON: /api/errors/2728f8e614db6705. Report an issue: GitHub.