{"record":{"id":"3c4048a46357a151","repo":"airbnb/lottie-android","slug":"lottieanimator-does-not-support-setstartdelay","errorCode":null,"errorMessage":"LottieAnimator does not support setStartDelay.","messagePattern":"LottieAnimator does not support setStartDelay\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"lottie/src/main/java/com/airbnb/lottie/utils/BaseLottieAnimator.java","lineNumber":22,"sourceCode":"import android.animation.TimeInterpolator;\nimport android.animation.ValueAnimator;\nimport android.os.Build;\n\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\npublic abstract class BaseLottieAnimator extends ValueAnimator {\n  private final Set<ValueAnimator.AnimatorUpdateListener> updateListeners = new CopyOnWriteArraySet<>();\n  private final Set<AnimatorListener> listeners = new CopyOnWriteArraySet<>();\n  private final Set<Animator.AnimatorPauseListener> pauseListeners = new CopyOnWriteArraySet<>();\n\n\n  @Override public long getStartDelay() {\n    throw new UnsupportedOperationException(\"LottieAnimator does not support getStartDelay.\");\n  }\n\n  @Override public void setStartDelay(long startDelay) {\n    throw new UnsupportedOperationException(\"LottieAnimator does not support setStartDelay.\");\n  }\n\n  @Override public ValueAnimator setDuration(long duration) {\n    throw new UnsupportedOperationException(\"LottieAnimator does not support setDuration.\");\n  }\n\n  @Override public void setInterpolator(TimeInterpolator value) {\n    throw new UnsupportedOperationException(\"LottieAnimator does not support setInterpolator.\");\n  }\n\n  public void addUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {\n    updateListeners.add(listener);\n  }\n\n  public void removeUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {\n    updateListeners.remove(listener);\n  }\n","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/airbnb/lottie-android/blob/05ea92e90381eb8a8ae06855ea2b74f322bebbec/lottie/src/main/java/com/airbnb/lottie/utils/BaseLottieAnimator.java#L4-L40","documentation":"BaseLottieAnimator overrides ValueAnimator.setStartDelay(long) to unconditionally throw UnsupportedOperationException. Lottie animations are frame-driven by the composition — the concept of a start delay does not map to Lottie's timing model. The override exists to fail explicitly rather than silently accept and ignore the call.","triggerScenarios":"Calling setStartDelay(ms) on a LottieValueAnimator. This can happen via direct call, or through Android framework code like AnimatorSet.play().after() which internally calls setStartDelay() on the animator. The throw is at BaseLottieAnimator.java:22.","commonSituations":"Using AnimatorSet to sequence a Lottie animation after others — AnimatorSet internally calls setStartDelay() which triggers this. Treating LottieValueAnimator as a drop-in ValueAnimator replacement in existing animation code. Chaining animations with standard Android patterns. Code migrated from ObjectAnimator that relied on setStartDelay.","solutions":["For delayed playback, use Handler.postDelayed or coroutine delay before calling LottieAnimationView.playAnimation() instead of setStartDelay()","If AnimatorSet triggers this, wrap the Lottie animation in a no-op ValueAnimator and sequence that instead, calling lottieAnimationView.playAnimation() in the no-op's onAnimationStart listener","Do not pass LottieValueAnimator to AnimatorSet.play().after() — this will call setStartDelay internally"],"exampleFix":"// before: animator.setStartDelay(500);\n// after:  // schedule playback externally\n//         handler.postDelayed(() -> lottieAnimationView.playAnimation(), 500);\n\n// For sequencing with AnimatorSet, use a proxy animator:\n// ValueAnimator proxy = ValueAnimator.ofInt(0, 1);\n// proxy.setDuration(0);\n// proxy.addListener(new AnimatorListenerAdapter() {\n//   @Override public void onAnimationStart(Animator a) {\n//     lottieAnimationView.playAnimation();\n//   }\n// });\n// AnimatorSet set = new AnimatorSet();\n// set.play(proxy).after(otherAnimator);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard against calling setStartDelay on LottieAnimator\nboolean isLottieAnimator(ValueAnimator animator) {\n  return animator instanceof com.airbnb.lottie.utils.BaseLottieAnimator;\n}\n\n// Safe access:\nvoid safeSetStartDelay(ValueAnimator animator, long delay) {\n  if (animator instanceof com.airbnb.lottie.utils.BaseLottieAnimator) {\n    throw new IllegalArgumentException(\"Use external scheduling for LottieAnimator delays\");\n  }\n  animator.setStartDelay(delay);\n}","tryCatchPattern":null,"preventionTips":["Never call setStartDelay() on a LottieValueAnimator","Do not pass LottieValueAnimator to AnimatorSet.play().after() — it calls setStartDelay internally","Use Handler.postDelayed or coroutine delay to schedule Lottie playback"],"tags":["lottie","animation","unsupported-operation","android"],"backgroundTag":null,"analyzedSha":"05ea92e90381eb8a8ae06855ea2b74f322bebbec","analyzedAt":"2026-08-14T00:51:35.636Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}