3b1b/manim · error · NotImplementedError
Method chaining is currently not supported for overridden an
Error message
Method chaining is currently not supported for overridden animations
What it means
NotImplementedError from _AnimBuilder.__getattr__ (manimlib/mobject/mobject.py:2157). The animate syntax builds a chain of method calls; some methods (e.g. certain VMobject/geometry methods) carry an _override_animate marker that swaps in a custom animation. Chaining further calls while such an overridden animation is already pending (or chaining after one within the same builder) is not supported by the builder's implementation, so it raises instead of producing a wrong animation.
Source
Thrown at manimlib/mobject/mobject.py:2157
class _AnimationBuilder:
def __init__(self, mobject: Mobject):
self.mobject = mobject
self.overridden_animation = None
self.mobject.generate_target()
self.is_chaining = False
self.methods: list[Callable] = []
self.anim_args = {}
self.can_pass_args = True
def __getattr__(self, method_name: str):
method = getattr(self.mobject.target, method_name)
self.methods.append(method)
has_overridden_animation = hasattr(method, "_override_animate")
if (self.is_chaining and has_overridden_animation) or self.overridden_animation:
raise NotImplementedError(
"Method chaining is currently not supported for " + \
"overridden animations"
)
def update_target(*method_args, **method_kwargs):
if has_overridden_animation:
self.overridden_animation = method._override_animate(
self.mobject, *method_args, **method_kwargs
)
else:
method(*method_args, **method_kwargs)
return self
self.is_chaining = True
return update_target
def __call__(self, **kwargs):
return self.set_anim_args(**kwargs)View on GitHub (pinned to dee01804d4)
Solutions
- Split the chain: play the overridden-animation call first, then chain the rest in a separate animate expression (self.play(mob.animate.a(...)) then self.play(mob.animate.shift(...)))
- Reorder so the overridden method is the LAST call in the chain
- Replace the overridden call with its non-animated equivalent wrapped in a Transform/ApplyMethod if chaining is essential
Example fix
# before self.play(mob.animate.move_to(ORIGIN).shift(RIGHT)) # if move_to had an _override_animate in your version -> NotImplementedError # after self.play(mob.animate.move_to(ORIGIN)) self.play(mob.animate.shift(RIGHT))
Defensive patterns
Strategy: fallback
Type guard
def has_override_animate(method) -> bool:
return hasattr(method, "_override_animate")
# check before chaining:
# method = getattr(mob, name)
# if has_override_animate(method): keep it last / play it alone Try / catch
try:
builder = mob.animate.move_to(p).shift(RIGHT)
except NotImplementedError:
builder = mob.animate.shift(RIGHT) # play overridden call separately Prevention
- Keep overridden-animation methods as the last call in an animate chain, or play them alone
- Split long chains into multiple self.play calls when in doubt
- Check for the _override_animate attribute when writing generic animation wrappers
When it happens
Trigger: mob.animate.some_overridden_method(...).shift(...) where some_overridden_method has an _override_animate attribute (methods wrapped via the override_animate decorator at mobject.py:2224); chaining two overridden-animation methods: mob.animate.a(...).b(...) where both are overridden; using is_chaining with an overridden method.
Common situations: Long fluent chains in scene code like circle.animate.move_to(x).set_fill(...).scale(2) where one link happens to be an animate-overridden method; library versions that add more _override_animate decorated methods, breaking previously working chains.
Related errors
- Animation arguments can only be passed by calling ``animate`
- Trying to restore without having saved
- Unsupported: {path_verb}
- At least 2 mobjects needed for Union.
- At least 2 mobjects needed for Intersection.
AI-assisted analysis of 3b1b/manim@dee01804d4 (2026-08-14).
Data as JSON: /api/errors/e59f6519ef70c452.
Report an issue: GitHub.