3b1b/manim · error · Exception

Only VMobjects can be passed into VGroup

Error message

Only VMobjects can be passed into VGroup

What it means

Raised by VGroup.__init__ (vectorized_mobject.py:1397) when any positional argument is an instance of Mobject but not of VMobject. Note the asymmetry with VMobject.add: non-Mobject arguments (e.g. an iterable of VMobjects, which _ingest_args expands) are allowed, but a concrete non-vectorized Mobject is rejected.

Source

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

        about_point: Vect3 | None = None,
        **kwargs
    ) -> Self:
        rot_matrix_T = rotation_matrix_transpose(angle, axis)
        self.apply_points_function(
            lambda points: np.dot(points, rot_matrix_T),
            about_point,
            **kwargs
        )
        for mob in self.get_family():
            mob.get_unit_normal(refresh=True)
        return self


class VGroup(Group, VMobject, Generic[SubVmobjectType]):
    def __init__(self, *vmobjects: SubVmobjectType | Iterable[SubVmobjectType], **kwargs):
        super().__init__(**kwargs)
        if any(isinstance(vmob, Mobject) and not isinstance(vmob, VMobject) for vmob in vmobjects):
            raise Exception("Only VMobjects can be passed into VGroup")
        self._ingest_args(*vmobjects)
        if self.submobjects:
            self.uniforms.update(self.submobjects[0].uniforms)

    def __add__(self, other: VMobject) -> Self:
        assert isinstance(other, VMobject)
        return self.add(other)

    # This is just here to make linters happy with references to things like VGroup(...)[0]
    def __getitem__(self, index) -> SubVmobjectType:
        return super().__getitem__(index)


class VectorizedPoint(Point, VMobject):
    def __init__(
        self,
        location: np.ndarray = ORIGIN,
        color: ManimColor = BLACK,

View on GitHub (pinned to dee01804d4)

Solutions

  1. Replace the non-VMobject argument with a VMobject equivalent (Group -> VGroup, Point -> a vectorized dot or remove it)
  2. Use Group(...) instead of VGroup(...) when you genuinely need to hold non-vectorized mobjects
  3. Unpack iterables explicitly and verify each element with isinstance(m, VMobject) before constructing the VGroup

Example fix

# before
inner = Group(Dot(), Circle())
outer = VGroup(inner)  # Group is a Mobject, not a VMobject -> raises

# after
inner = VGroup(Dot(), Circle())
outer = VGroup(inner)
Defensive patterns

Strategy: type-guard

Validate before calling

flat = []
for arg in args:
    flat.extend(arg if isinstance(arg, (list, tuple)) else [arg])
assert all(isinstance(m, VMobject) for m in flat)
vg = VGroup(*flat)

Type guard

from manimlib import VMobject, Mobject

def is_vmobject(m) -> bool:
    return isinstance(m, VMobject) and not (isinstance(m, Mobject) and not isinstance(m, VMobject))

Prevention

When it happens

Trigger: VGroup(Group(...)), VGroup(Mobject()), VGroup(Point(...), Dot()) (Point is not a VMobject), or VGroup(Points()/a PMobject). Passing a plain list [Dot(), Dot()] does NOT raise because a list is not a Mobject; it is ingested instead.

Common situations: Nesting a Group inside VGroup for organizational purposes; passing a mixed list where one element is an ImageMobject or point-cloud mobject; copy-pasting Group construction into VGroup code during refactors.

Related errors


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