{"record":{"id":"d9491b92ed956aff","repo":"airbnb/lottie-android","slug":"cannot-call-getkeyframes-on-animatablesplitdimensi","errorCode":null,"errorMessage":"Cannot call getKeyframes on AnimatableSplitDimensionPathValue.","messagePattern":"Cannot call getKeyframes on AnimatableSplitDimensionPathValue\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableSplitDimensionPathValue.java","lineNumber":24,"sourceCode":"import com.airbnb.lottie.animation.keyframe.SplitDimensionPathKeyframeAnimation;\nimport com.airbnb.lottie.value.Keyframe;\n\nimport java.util.List;\n\npublic class AnimatableSplitDimensionPathValue implements AnimatableValue<PointF, PointF> {\n  private final AnimatableFloatValue animatableXDimension;\n  private final AnimatableFloatValue animatableYDimension;\n\n  public AnimatableSplitDimensionPathValue(\n      AnimatableFloatValue animatableXDimension,\n      AnimatableFloatValue animatableYDimension) {\n    this.animatableXDimension = animatableXDimension;\n    this.animatableYDimension = animatableYDimension;\n  }\n\n  @Override\n  public List<Keyframe<PointF>> getKeyframes() {\n    throw new UnsupportedOperationException(\"Cannot call getKeyframes on AnimatableSplitDimensionPathValue.\");\n  }\n\n  @Override\n  public boolean isStatic() {\n    return animatableXDimension.isStatic() && animatableYDimension.isStatic();\n  }\n\n  @Override public BaseKeyframeAnimation<PointF, PointF> createAnimation() {\n    return new SplitDimensionPathKeyframeAnimation(\n        animatableXDimension.createAnimation(), animatableYDimension.createAnimation());\n  }\n}\n","sourceCodeStart":6,"sourceCodeEnd":37,"githubUrl":"https://github.com/airbnb/lottie-android/blob/05ea92e90381eb8a8ae06855ea2b74f322bebbec/lottie/src/main/java/com/airbnb/lottie/model/animatable/AnimatableSplitDimensionPathValue.java#L6-L37","documentation":"AnimatableSplitDimensionPathValue implements the AnimatableValue<PointF, PointF> interface, which declares getKeyframes(), but this implementation derives its PointF by merging two independent AnimatableFloatValue tracks (one for X, one for Y) via SplitDimensionPathKeyframeAnimation. It has no keyframe list of its own, so calling getKeyframes() is an intentional contract violation that throws UnsupportedOperationException. The library never calls this method internally on this type; it only arises when application code treats all AnimatableValue instances polymorphically and calls getKeyframes() generically.","triggerScenarios":"Calling .getKeyframes() on an AnimatableValue that is actually an AnimatableSplitDimensionPathValue instance — typically through a generic loop or utility that processes any AnimatableValue<PointF, PointF> without instanceof checks. Also triggered by reflection-based code or serialization frameworks that invoke all interface methods.","commonSituations":"Writing generic keyframe-inspection tooling that iterates over all animatable properties in a LottieComposition; building a Lottie animation validator/debugger; migrating from a code path that previously only encountered AnimatablePathValue (which does support getKeyframes) to one that now also encounters split-dimension anchor points.","solutions":["Guard with instanceof: check `if (animatableValue instanceof AnimatableSplitDimensionPathValue)` before calling getKeyframes(), and skip or handle it separately.","Call isStatic() or createAnimation() instead — both are fully supported on this type and provide the information you likely need.","If you need the underlying keyframes, access them via getAnimatableXDimension().getKeyframes() and getAnimatableYDimension().getKeyframes() (requires extending the class or adding accessors)."],"exampleFix":"// before\nfor (AnimatableValue<PointF, PointF> v : animatableValues) {\n    List<Keyframe<PointF>> keys = v.getKeyframes(); // throws on split-dimension\n    process(keys);\n}\n\n// after\nfor (AnimatableValue<PointF, PointF> v : animatableValues) {\n    if (v instanceof AnimatableSplitDimensionPathValue) {\n        continue; // no unified keyframes; use createAnimation() instead\n    }\n    List<Keyframe<PointF>> keys = v.getKeyframes();\n    process(keys);\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Type guard before calling getKeyframes()\npublic static boolean hasKeyframes(AnimatableValue<?, ?> value) {\n    return !(value instanceof AnimatableSplitDimensionPathValue);\n}","tryCatchPattern":null,"preventionTips":["Never call getKeyframes() generically on AnimatableValue without an instanceof check for AnimatableSplitDimensionPathValue.","Prefer isStatic() or createAnimation() which are safe across all AnimatableValue implementations.","If building generic animatable-value tooling, document that AnimatableSplitDimensionPathValue is a special case."],"tags":["lottie","api-contract","unsupported-operation","animatable-value"],"backgroundTag":null,"analyzedSha":"05ea92e90381eb8a8ae06855ea2b74f322bebbec","analyzedAt":"2026-08-14T00:51:35.636Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}