airbnb/lottie-android · error · IllegalArgumentException

You must provide a static value in the constructor , call se

Error message

You must provide a static value in the constructor , call setValue, or override getValue.

What it means

LottieRelativePointValueCallback adds an offset to the animation's interpolated PointF on every frame. Its default getOffset() returns the inherited `value` field, which is null unless supplied. The library throws IllegalArgumentException when the keyframe animation first evaluates this callback and finds `value == null`. Note the message text ('override getValue') is copy-pasted from the base class; for this relative callback the correct override is getOffset, and getValue is already declared final.

Source

Thrown at lottie/src/main/java/com/airbnb/lottie/value/LottieRelativePointValueCallback.java:47

            frameInfo.getEndValue().x,
            frameInfo.getInterpolatedKeyframeProgress()),
        MiscUtils.lerp(
            frameInfo.getStartValue().y,
            frameInfo.getEndValue().y,
            frameInfo.getInterpolatedKeyframeProgress())
    );

    PointF offset = getOffset(frameInfo);
    point.offset(offset.x, offset.y);
    return point;
  }

  /**
   * Override this to provide your own offset on every frame.
   */
  public PointF getOffset(LottieFrameInfo<PointF> frameInfo) {
    if (value == null) {
      throw new IllegalArgumentException("You must provide a static value in the constructor " +
          ", call setValue, or override getValue.");
    }
    return value;
  }
}

View on GitHub (pinned to 05ea92e903)

Solutions

  1. Supply the offset via constructor: `new LottieRelativePointValueCallback(new PointF(10f, 5f))`.
  2. Or call `callback.setValue(new PointF(x, y))` before/while the animation runs to set or update the offset.
  3. Or subclass and override `getOffset(LottieFrameInfo<PointF> frameInfo)` to return a computed PointF per frame (not getValue, which is final here).
  4. Confirm the registered LottieProperty is point-typed; binding this callback to a non-point property yields the same null evaluation.

Example fix

// before
LottieRelativePointValueCallback cb = new LottieRelativePointValueCallback();
animationView.addValueCallback(keyPath, LottieProperty.TRANSFORM_POSITION, cb); // throws on first frame

// after — option A: static offset point
LottieRelativePointValueCallback cb =
    new LottieRelativePointValueCallback(new PointF(0f, 50f));

// after — option B: per-frame offset
cb = new LottieRelativePointValueCallback() {
  @Override
  public PointF getOffset(LottieFrameInfo<PointF> frameInfo) {
    return new PointF((float) Math.sin(frameInfo.getOverallProgress() * Math.PI * 2) * 20f, 0f);
  }
};
Defensive patterns

Strategy: validation

Validate before calling

LottieRelativePointValueCallback cb;
boolean ok;
try {
  cb.getOffset(new com.airbnb.lottie.value.LottieFrameInfo<android.graphics.PointF>());
  ok = true;
} catch (IllegalArgumentException e) {
  ok = false;
}
if (!ok) {
  cb = new LottieRelativePointValueCallback(new android.graphics.PointF(0f, 0f));
}

Type guard

// Enforce initialization through factories that require an offset or an override:
static LottieRelativePointValueCallback offset(android.graphics.PointF p) {
  return new LottieRelativePointValueCallback(p);
}
static LottieRelativePointValueCallback offset(java.util.function.Function<com.airbnb.lottie.value.LottieFrameInfo<android.graphics.PointF>, android.graphics.PointF> fn) {
  return new LottieRelativePointValueCallback() {
    @Override public android.graphics.PointF getOffset(com.airbnb.lottie.value.LottieFrameInfo<android.graphics.PointF> frameInfo) { return fn.apply(frameInfo); }
  };
}

Try / catch

// Programmer error — prefer to fix, not catch. Defensive isolation only:
try {
  animationView.addValueCallback(keyPath, LottieProperty.TRANSFORM_POSITION, cb);
  animationView.invalidate();
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("static value")) {
    cb.setValue(new android.graphics.PointF(0f, 0f));
  } else { throw e; }
}

Prevention

When it happens

Trigger: Constructing `new LottieRelativePointValueCallback()` (no-arg) and registering it via addValueCallback on a position-typed LottieProperty (TRANSFORM_POSITION, POSITION, ELLIPSE_POSITION, etc.) without calling setValue or overriding getOffset. The throw occurs during BaseKeyframeAnimation value resolution on the first frame the property is needed, inside the draw pass.

Common situations: Using the Relative variant where plain LottieValueCallback<PointF> was intended (the Relative one requires an offset, not an absolute point); passing a PointF to setValue that was itself null; assuming getOffset returns PointF(0,0) by default; rebinding the callback to a different KeyPath at runtime after forgetting to re-initialize value; Lottie version change that no longer tolerates the uninitialized path.

Related errors


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