airbnb/lottie-android · error · IllegalArgumentException

minFrame (%s) must be <= maxFrame (%s)

Error message

minFrame (%s) must be <= maxFrame (%s)

What it means

Thrown by LottieValueAnimator.setMinAndMaxFrames() when the minFrame parameter is greater than the maxFrame parameter. The frame range must be valid (min <= max) for the animator to produce a meaningful playback window. The check at line 196 (`minFrame > maxFrame`) guards against inverted ranges that would cause undefined playback behavior.

Source

Thrown at lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java:197

      return;
    }
    this.frameRaw = MiscUtils.clamp(frame, getMinFrame(), getMaxFrame());
    this.frame = useCompositionFrameRate ? ((float) Math.floor(frameRaw)) : frameRaw;
    lastFrameTimeNs = 0;
    notifyUpdate();
  }

  public void setMinFrame(int minFrame) {
    setMinAndMaxFrames(minFrame, (int) maxFrame);
  }

  public void setMaxFrame(float maxFrame) {
    setMinAndMaxFrames(minFrame, maxFrame);
  }

  public void setMinAndMaxFrames(float minFrame, float maxFrame) {
    if (minFrame > maxFrame) {
      throw new IllegalArgumentException(String.format("minFrame (%s) must be <= maxFrame (%s)", minFrame, maxFrame));
    }
    float compositionMinFrame = composition == null ? -Float.MAX_VALUE : composition.getStartFrame();
    float compositionMaxFrame = composition == null ? Float.MAX_VALUE : composition.getEndFrame();
    float newMinFrame = MiscUtils.clamp(minFrame, compositionMinFrame, compositionMaxFrame);
    float newMaxFrame = MiscUtils.clamp(maxFrame, compositionMinFrame, compositionMaxFrame);
    if (newMinFrame != this.minFrame || newMaxFrame != this.maxFrame) {
      this.minFrame = newMinFrame;
      this.maxFrame = newMaxFrame;
      setFrame((int) MiscUtils.clamp(frame, newMinFrame, newMaxFrame));
    }
  }

  public void reverseAnimationSpeed() {
    setSpeed(-getSpeed());
  }

  public void setSpeed(float speed) {
    this.speed = speed;

View on GitHub (pinned to 05ea92e903)

Solutions

  1. Ensure minFrame <= maxFrame before calling setMinAndMaxFrames(); validate or swap arguments if needed
  2. When calling setMinFrame() or setMaxFrame() individually, ensure the new value doesn't cross the existing boundary — set both together if unsure
  3. Use the composition's frame range as a reference: get it via LottieComposition.getStartFrame()/getEndFrame() to compute valid bounds

Example fix

// before: animator.setMinAndMaxFrames(60, 30);  // min > max
// after:  int lo = Math.min(30, 60);
//         int hi = Math.max(30, 60);
//         animator.setMinAndMaxFrames(lo, hi);

// or validate against composition bounds:
// float compStart = composition.getStartFrame();
// float compEnd = composition.getEndFrame();
// float min = MiscUtils.clamp(requestedMin, compStart, compEnd);
// float max = MiscUtils.clamp(requestedMax, min, compEnd);
// animator.setMinAndMaxFrames(min, max);
Defensive patterns

Strategy: validation

Validate before calling

// Validate frame range before setting
void safeSetMinAndMaxFrames(LottieValueAnimator animator, float min, float max) {
  if (min > max) {
    throw new IllegalArgumentException(
      "minFrame (" + min + ") must be <= maxFrame (" + max + ")");
  }
  animator.setMinAndMaxFrames(min, max);
}

// Or swap to ensure order:
void setFramesSafe(LottieValueAnimator animator, float a, float b) {
  float min = Math.min(a, b);
  float max = Math.max(a, b);
  animator.setMinAndMaxFrames(min, max);
}

Try / catch

try {
  animator.setMinAndMaxFrames(minFrame, maxFrame);
} catch (IllegalArgumentException e) {
  Log.w(TAG, "Invalid frame range: " + e.getMessage());
  // fall back to composition defaults
  animator.setMinAndMaxFrame(composition);
}

Prevention

When it happens

Trigger: Calling setMinAndMaxFrames(min, max) where min > max. This can also happen indirectly via setMinFrame(x) (which calls setMinAndMaxFrames(x, currentMaxFrame)) if x is greater than the current maxFrame, or via setMaxFrame(x) if x is less than the current minFrame. The throw is at LottieValueAnimator.java:197.

Common situations: Programmatically setting frame bounds with reversed arguments (min and max swapped). Calling setMinFrame() with a value larger than the current maxFrame without updating maxFrame first. Dynamic frame range calculation that produces an inverted range due to a logic error. Using user input or computed values without range validation.

Related errors


AI-assisted analysis of airbnb/lottie-android@05ea92e903 (2026-08-14). Data as JSON: /api/errors/bdb347494120240c. Report an issue: GitHub.