Skip to content

MLC104: literal non-positive run_time or wait duration

qual reports MLC104 when a played call carries a literal duration of zero or less:

  • self.wait(<literal <= 0>) / self.wait(duration=<literal <= 0>) / self.pause(<literal <= 0>) reached from a Scene lifecycle
  • self.play(..., run_time=<literal <= 0>) — the kwarg is set onto every animation, so it is the whole-play duration
  • a literal run_time <= 0 on a curated animation constructor written directly as an argument of a played play, e.g. self.play(FadeIn(mob, run_time=0)) or self.play(Wait(0)) (Wait's first positional parameter is run_time)

Manim validates durations when the play executes, not when an animation is constructed: Scene.validate_run_time rejects a non-positive whole-play or wait duration with ValueError, and an animation with a non-positive run_time inside a longer play divides by zero in the per-frame interpolation (alpha = t / animation.run_time). Constructing Wait(run_time=0) without ever playing it is harmless, so unplayed constructions never fire.

  • Default severity: error
  • Minimum confidence: certain
  • Implementation phase: 1
  • Fix: none

Only syntactic literal proofs on the played call fire: variables, expressions, values routed through reassignable state, and anything Unknown stay silent. A play-level run_time kwarg (or a **kwargs splat on the play) overrides every constructor run time, so constructor literals are not reported then.

Plays reached through project helpers fire at the play call inside the helper body: self.<helper>() methods, module-level helpers taking the scene as a parameter (flourish(self, mob)), and helpers imported from other project files alike — the diagnostic anchors in the helper's file. Behind a recursion or inline-depth frontier the literal duration survives on the summary-derived play record, so the check still fires there; third-party helpers are never analyzed.

Wrong

class Demo(Scene):
    def construct(self):
        self.play(Create(Square()), run_time=0)
        self.play(FadeIn(Square(), run_time=0))
        self.wait(-1.5)
class Demo(Scene):
    def construct(self):
        self.play(Create(Square()), run_time=2)
        self.play(FadeIn(Square(), run_time=0), run_time=2)  # kwarg overrides
        self.wait(0.5)
        unplayed = Wait(run_time=0)  # construction alone never validates