#3213·lottie-web

Completion compares the pass counter with strict equality, so an overshot counter loops forever

Author: GamoteCreated Aug 12, 2026Updated Aug 12, 2026

advanceTime decides completion with:

javascript
if (!this.loop || this.playCount === this.loop) {

Because the comparison is exact equality, any state where playCount is already above loop can never complete, and the animation loops forever.

The counter overshoots through the public API alone: with loop: true, every pass runs this.playCount += 1 unbounded. Calling setLoop(2) after four passes then asks a counter sitting at 4 to equal 2:

javascript
const anim = lottie.loadAnimation({
  container,
  renderer: "svg",
  autoplay: true,
  loop: true,
  animationData: shortAnimation,
});
// after four loopComplete events:
anim.setLoop(2);
// never completes: playCount is 4, and only playCount === 2 would stop it

The reverse path has the same shape with the mirrored guard (this.playCount-- counts down and the check is against 0), so a counter pushed past either bound is permanently unstoppable.

Comparing with >= in the forward branch (and the symmetric fix in the reverse one) makes an overshot counter complete at the next boundary instead.

Related: #3214, where an untyped setLoop value reaches the same comparison.