Skip to content

MLC105: updater callback cannot bind to Manim's invocation

qual reports MLC105 when a callback registered with Mobject.add_updater or Scene.add_updater provably cannot bind to the positional call Manim actually makes (DESIGN §3.3):

  • Mobject.add_updater inspects the callback signature; when any parameter is named dt the callback is invoked as callback(mobject, dt), otherwise as callback(mobject).
  • Scene.add_updater always invokes callback(dt) with one positional argument.

The rule simulates Python binding (inspect.Signature.bind semantics) over the declared parameters — positional-only, positional-or-keyword, *args, keyword-only, **kwargs, and defaults. A signature that cannot bind raises TypeError on the first rendered frame.

  • Default severity: error
  • Minimum confidence: high
  • Implementation phase: 1
  • Fix: none (renaming parameters outside an inline lambda is unsafe)

Callbacks whose signature cannot be resolved, and method references whose binding cannot be proven (a leading self parameter), stay silent.

Wrong

class Demo(Scene):
    def construct(self):
        square = Square()
        square.add_updater(lambda dt: dt)          # called as (mobject, dt)
        square.add_updater(lambda mob, delta: mob)  # called as (mobject)
class Demo(Scene):
    def construct(self):
        square = Square()
        square.add_updater(lambda mob, dt: mob.shift(dt * RIGHT))
        square.add_updater(lambda mob: mob.next_to(anchor))