{"record":{"id":"a5feb485f26a194e","repo":"3b1b/manim","slug":"whoops-looks-like-you-accidentally-invoked-the-me","errorCode":null,"errorMessage":"Whoops, looks like you accidentally invoked the method you want to animate","messagePattern":"Whoops, looks like you accidentally invoked the method you want to animate","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"manimlib/animation/transform.py","lineNumber":173,"sourceCode":"\nclass ApplyMethod(Transform):\n    def __init__(self, method: Callable, *args, **kwargs):\n        \"\"\"\n        method is a method of Mobject, *args are arguments for\n        that method.  Key word arguments should be passed in\n        as the last arg, as a dict, since **kwargs is for\n        configuration of the transform itself\n\n        Relies on the fact that mobject methods return the mobject\n        \"\"\"\n        self.check_validity_of_input(method)\n        self.method = method\n        self.method_args = args\n        super().__init__(method.__self__, **kwargs)\n\n    def check_validity_of_input(self, method: Callable) -> None:\n        if not inspect.ismethod(method):\n            raise Exception(\n                \"Whoops, looks like you accidentally invoked \"\n                \"the method you want to animate\"\n            )\n        assert isinstance(method.__self__, Mobject)\n\n    def create_target(self) -> Mobject:\n        method = self.method\n        # Make sure it's a list so that args.pop() works\n        args = list(self.method_args)\n\n        if len(args) > 0 and isinstance(args[-1], dict):\n            method_kwargs = args.pop()\n        else:\n            method_kwargs = {}\n        target = method.__self__.copy()\n        method.__func__(target, *args, **method_kwargs)\n        return target\n","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/animation/transform.py#L155-L191","documentation":"ApplyMethod wraps a bound mobject method (e.g. circle.shift) and animates applying it. check_validity_of_input requires inspect.ismethod(method): passing the method's *return value* — i.e. calling it — fails, because the animation needs the callable plus separate args to build the target state.","triggerScenarios":"ApplyMethod(circle.shift(RIGHT)) instead of ApplyMethod(circle.shift, RIGHT); passing a free function or lambda instead of a bound method; passing mobject.copy() (returns a Mobject, not a method).","commonSituations":"Muscle memory from scene.play(circle.shift(RIGHT)); migrating old scripts that mixed direct method calls with ApplyMethod; using .animate and ApplyMethod inconsistently in the same file.","solutions":["Pass the method uninvoked with its arguments separately: ApplyMethod(circle.shift, RIGHT)","Prefer the modern syntax: self.play(circle.animate.shift(RIGHT))","For functions that are not mobject methods, use ApplyFunction(function, mobject) instead"],"exampleFix":"# before\nself.play(ApplyMethod(circle.shift(RIGHT)))\n# after\nself.play(ApplyMethod(circle.shift, RIGHT))\n# or\nself.play(circle.animate.shift(RIGHT))","handlingStrategy":"type-guard","validationCode":"import inspect\nassert inspect.ismethod(circle.shift), \"pass the method itself, not its result\"","typeGuard":"import inspect\ndef is_bound_mobject_method(f) -> bool:\n    return inspect.ismethod(f) and isinstance(f.__self__, Mobject)","tryCatchPattern":null,"preventionTips":["Standardize on mob.animate.method(args) — it removes the call-vs-reference ambiguity entirely","In code review, flag any ApplyMethod(...) whose first argument ends in ')' "],"tags":["animation","transform","api-misuse","validation"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}