{"record":{"id":"e02577e628a587a2","repo":"3b1b/manim","slug":"self-class-name-create-target-not-proper","errorCode":null,"errorMessage":"{self.__class__.__name__}.create_target not properly implemented","messagePattern":"(.+?)\\.create_target not properly implemented","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"manimlib/animation/transform.py","lineNumber":77,"sourceCode":"            # Nothing to align, so nothing is done to the target and it can stand as it is\n            self.target_copy = self.target_mobject\n        else:\n            # Use a copy of target_mobject for the align_data_and_family\n            # call so that the actual target_mobject stays\n            # preserved, since calling align_data will potentially\n            # change the structure of both arguments\n            self.target_copy = self.target_mobject.copy()\n            self.mobject.align_data_and_family(self.target_copy)\n        super().begin()\n\n    def create_target(self) -> Mobject:\n        # Has no meaningful effect here, but may be useful\n        # in subclasses\n        return self.target_mobject\n\n    def check_target_mobject_validity(self) -> None:\n        if self.target_mobject is None:\n            raise Exception(\n                f\"{self.__class__.__name__}.create_target not properly implemented\"\n            )\n\n    def clean_up_from_scene(self, scene: Scene) -> None:\n        super().clean_up_from_scene(scene)\n        if self.replace_mobject_with_target_in_scene:\n            scene.remove(self.mobject)\n            scene.add(self.target_mobject)\n\n    def update_config(self, **kwargs) -> None:\n        Animation.update_config(self, **kwargs)\n        if \"path_arc\" in kwargs:\n            self.path_func = path_along_arc(\n                kwargs[\"path_arc\"],\n                kwargs.get(\"path_arc_axis\", OUT)\n            )\n\n    def get_all_mobjects(self) -> list[Mobject]:","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/animation/transform.py#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass the target explicitly: Transform(mobject, target_mobject)","In a subclass, either set self.target_mobject = ... before super().begin(), or override create_target() to build and return the target mobject","Ensure your subclass __init__ chains to Transform.__init__ with both mobject and target arguments"],"exampleFix":"# before\nclass MyTransform(Transform):\n    def __init__(self, mobject, **kwargs):\n        super().__init__(mobject, **kwargs)  # no target given\n# after\nclass MyTransform(Transform):\n    def __init__(self, mobject, **kwargs):\n        super().__init__(mobject, mobject.copy().scale(2), **kwargs)","handlingStrategy":"type-guard","validationCode":"anim = MyTransform(mob)\nassert anim.target_mobject is not None or type(anim).create_target is not Transform.create_target","typeGuard":"def has_target(anim: Transform) -> bool:\n    return getattr(anim, \"target_mobject\", None) is not None or type(anim).create_target is not Transform.create_target","tryCatchPattern":null,"preventionTips":["In Transform subclasses, always chain __init__ to super().__init__(mobject, target_mobject)","Override create_target() rather than poking target_mobject when the target is computed"],"tags":["animation","transform","subclassing","validation"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}