3b1b/manim · error · Exception

{self.__class__.__name__}.create_target not properly impleme

Error message

{self.__class__.__name__}.create_target not properly implemented

What it means

Transform animations build their destination from create_target(); the base Transform.create_target just returns self.target_mobject. check_target_mobject_validity is invoked when target_mobject is None, meaning a subclass never assigned it nor overrode create_target, so the animation has nothing to interpolate toward.

Source

Thrown at manimlib/animation/transform.py:77

            # Nothing to align, so nothing is done to the target and it can stand as it is
            self.target_copy = self.target_mobject
        else:
            # Use a copy of target_mobject for the align_data_and_family
            # call so that the actual target_mobject stays
            # preserved, since calling align_data will potentially
            # change the structure of both arguments
            self.target_copy = self.target_mobject.copy()
            self.mobject.align_data_and_family(self.target_copy)
        super().begin()

    def create_target(self) -> Mobject:
        # Has no meaningful effect here, but may be useful
        # in subclasses
        return self.target_mobject

    def check_target_mobject_validity(self) -> None:
        if self.target_mobject is None:
            raise Exception(
                f"{self.__class__.__name__}.create_target not properly implemented"
            )

    def clean_up_from_scene(self, scene: Scene) -> None:
        super().clean_up_from_scene(scene)
        if self.replace_mobject_with_target_in_scene:
            scene.remove(self.mobject)
            scene.add(self.target_mobject)

    def update_config(self, **kwargs) -> None:
        Animation.update_config(self, **kwargs)
        if "path_arc" in kwargs:
            self.path_func = path_along_arc(
                kwargs["path_arc"],
                kwargs.get("path_arc_axis", OUT)
            )

    def get_all_mobjects(self) -> list[Mobject]:

View on GitHub (pinned to dee01804d4)

Solutions

  1. Pass the target explicitly: Transform(mobject, target_mobject)
  2. In a subclass, either set self.target_mobject = ... before super().begin(), or override create_target() to build and return the target mobject
  3. Ensure your subclass __init__ chains to Transform.__init__ with both mobject and target arguments

Example fix

# before
class MyTransform(Transform):
    def __init__(self, mobject, **kwargs):
        super().__init__(mobject, **kwargs)  # no target given
# after
class MyTransform(Transform):
    def __init__(self, mobject, **kwargs):
        super().__init__(mobject, mobject.copy().scale(2), **kwargs)
Defensive patterns

Strategy: type-guard

Validate before calling

anim = MyTransform(mob)
assert anim.target_mobject is not None or type(anim).create_target is not Transform.create_target

Type guard

def has_target(anim: Transform) -> bool:
    return getattr(anim, "target_mobject", None) is not None or type(anim).create_target is not Transform.create_target

Prevention

When it happens

Trigger: Subclassing Transform, overriding __init__ without calling super().__init__(mobject, target) and without setting self.target_mobject, then playing the animation. Also calling Transform's begin() on a manually constructed instance that skipped target setup.

Common situations: Writing custom transform-like animations; refactoring a subclass's __init__ and dropping the super() call; porting an animation from an older manim version where targets were set differently.

Related errors


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