3b1b/manim · error · Exception

All submobjects must be of type VMobject

Error message

All submobjects must be of type VMobject

What it means

Raised by VMobject.add (vectorized_mobject.py:245) when any argument passed to .add() is not an instance of VMobject. VMobject-only containers (vectorized mobjects rendered with stroke/fill shaders) cannot hold arbitrary Mobjects such as point-cloud PMobjects or bare Mobjects, so the type is enforced on every add call.

Source

Thrown at manimlib/mobject/types/vectorized_mobject.py:245

            stroke_width_in_scene_units=float(self.stroke_width_in_scene_units),
            # A filled VMobject is taken to be flat, which is what lets its normal
            # be one value rather than one per point, and what makes the winding
            # count deciding its interior meaningful in the first place
            unit_normal=np.array(OUT, dtype=float),
            # A fill is one flat region of one color, so unlike stroke there is
            # nothing for a per point value to mean
            fill_rgba=np.zeros(4),
            # A second color, equal to the first unless a gradient was asked for,
            # along with the two points it runs between, see inserts/fill_color.wgsl
            fill_rgba_end=np.zeros(4),
            gradient_start=np.zeros(3),
            gradient_end=np.zeros(3),
            fill_border_width=float(self.fill_border_width),
        )

    def add(self, *vmobjects: VMobject) -> Self:
        if not all((isinstance(m, VMobject) for m in vmobjects)):
            raise Exception("All submobjects must be of type VMobject")
        return super().add(*vmobjects)

    # Colors
    def init_colors(self):
        self.set_stroke(
            color=self.stroke_color,
            width=self.stroke_width,
            opacity=self.stroke_opacity,
            behind=self.stroke_behind,
        )
        self.set_fill(
            color=self.fill_color,
            opacity=self.fill_opacity,
            border_width=self.fill_border_width,
        )
        self.set_shading(*self.shading)
        self.set_flat_stroke(self.flat_stroke)
        self.color = self.get_color()

View on GitHub (pinned to dee01804d4)

Solutions

  1. Add only VMobject instances; convert the offending item to a VMobject type (e.g. use VGroup instead of Group, or wrap non-vectorized content appropriately)
  2. If you need to mix non-VMobject mobjects, use the generic Mobject.add / Group container instead of a VMobject/VGroup container
  3. Check types before adding: filter with isinstance(m, VMobject) to find which element fails

Example fix

# before
vg = VGroup()
vg.add(Group(Dot(), Dot()))  # Group is not a VMobject -> raises

# after
vg = VGroup()
vg.add(Dot(), Dot())
Defensive patterns

Strategy: type-guard

Validate before calling

vmobs = [m for m in candidates if isinstance(m, VMobject)]
container.add(*vmobs)

Type guard

from manimlib.mobject.types.vectorized_mobject import VMobject

def all_vmobjects(mobs) -> bool:
    return all(isinstance(m, VMobject) for m in mobs)

Prevention

When it happens

Trigger: Calling some_vgroup.add(Dot()) is fine; raising calls include dot.add(PMobject-instance), vgroup.add(Mobject()), or adding a Group (which is an Mobject but not a VMobject) into a VMobject: VGroup().add(Group(Dot())) raises.

Common situations: Mixing Mobject subclasses into a VGroup via .add() instead of the constructor; refactoring code that used generic Mobject containers; passing a Group of images or a Point (non-vectorized mobject) into a VGroup-based scene layout.

Related errors


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