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
- Supply the offset via constructor: `new LottieRelativePointValueCallback(new PointF(10f, 5f))`.
- Or call `callback.setValue(new PointF(x, y))` before/while the animation runs to set or update the offset.
- Or subclass and override `getOffset(LottieFrameInfo<PointF> frameInfo)` to return a computed PointF per frame (not getValue, which is final here).
- 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
- The Relative Point callback needs an OFFSET point, not an absolute position — don't confuse it with LottieValueCallback<PointF>.
- Disallow the no-arg constructor in your codebase unless getOffset is overridden in the same expression.
- Dry-test each callback: construct it and call getOffset(new LottieFrameInfo<>()) in a unit test before shipping.
- Check the bound LottieProperty is point-typed; a mismatch still triggers the null evaluation.
- During Lottie upgrades, smoke-test every screen using dynamic position callbacks on frame one.
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
- You must provide a static value in the constructor , call se
- LottieAnimator does not support getStartDelay.
- LottieAnimator does not support setStartDelay.
- LottieAnimator does not support setDuration.
- LottieAnimator does not support setInterpolator.
AI-assisted analysis of airbnb/lottie-android@05ea92e903 (2026-08-14).
Data as JSON: /api/errors/c04e46d0f08959ec.
Report an issue: GitHub.