{"record":{"id":"92a24688438b329f","repo":"Unity-Technologies/UnityCsReference","slug":"keyframes-must-be-non-null","errorCode":null,"errorMessage":"keyframes must be non-null","messagePattern":"keyframes must be non-null","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/Animation/AnimationUtility.bindings.cs","lineNumber":247,"sourceCode":"        extern internal static PropertyModification EditorCurveBindingToPropertyModification(EditorCurveBinding binding, [NotNull] GameObject gameObject);\n\n        extern public static EditorCurveBinding[] GetCurveBindings([NotNull] AnimationClip clip);\n        extern public static EditorCurveBinding[] GetObjectReferenceCurveBindings([NotNull] AnimationClip clip);\n\n        extern public static ObjectReferenceKeyframe[] GetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding);\n\n        public static void SetObjectReferenceCurve(AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes)\n        {\n            Internal_SetObjectReferenceCurve(clip, binding, keyframes, true);\n            Internal_InvokeOnCurveWasModified(clip, binding, keyframes != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);\n        }\n\n        public static void SetObjectReferenceCurves(AnimationClip clip, EditorCurveBinding[] bindings, ObjectReferenceKeyframe[][] keyframes)\n        {\n            if (bindings == null)\n                throw new ArgumentNullException(nameof(bindings), $\"{nameof(bindings)} must be non-null\");\n            if (keyframes == null)\n                throw new ArgumentNullException(nameof(keyframes), $\"{nameof(keyframes)} must be non-null\");\n            if (bindings.Length != keyframes.Length)\n                throw new InvalidOperationException($\"{nameof(bindings)} and {nameof(keyframes)} must be of equal length\");\n\n            int length = bindings.Length;\n            for (int i = 0; i < length; i++)\n            {\n                SetObjectReferenceCurveNoSync(clip, bindings[i], keyframes[i]);\n            }\n            SyncEditorCurves(clip);\n            Internal_InvokeOnCurveWasModified(clip, new EditorCurveBinding(), CurveModifiedType.ClipModified);\n        }\n\n        internal static void SetObjectReferenceCurveNoSync(AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes)\n        {\n            Internal_SetObjectReferenceCurve(clip, binding, keyframes, false);\n            Internal_InvokeOnCurveWasModified(clip, binding, keyframes != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);\n        }\n","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/Animation/AnimationUtility.bindings.cs#L229-L265","documentation":"Thrown by AnimationUtility.SetObjectReferenceCurves when the keyframes array (the jagged ObjectReferenceKeyframe[][]) is null. It is checked right after bindings so that the subsequent length-comparison guard has a real Length on both sides. SetObjectReferenceCurve (singular) allows null keyframes to delete a curve, but the plural batch form requires non-null.","triggerScenarios":"Calling SetObjectReferenceCurves(clip, bindings, null). A collector that returns null for 'no keyframes' instead of an empty jagged array. Deserialized keyframe data where the outer array node was missing.","commonSituations":"Programmatic clip generation that conditionally produces keyframes and defaults to null. JSON/serialization round-trips where an empty keyframes list serialized as null on load. Copy-paste from the singular API where null is legal.","solutions":["Default keyframes to an empty jagged array when there is nothing to write.","Build keyframes to exactly mirror bindings length, element for element.","Map a null result to Array.Empty<ObjectReferenceKeyframe[]>() at the boundary.","If you intend to delete all curves, call SetObjectReferenceCurve per binding with null instead of the batch API."],"exampleFix":"// before\nvar keyframes = clipData.HasKeyframes ? BuildKeyframes() : null;\nAnimationUtility.SetObjectReferenceCurves(clip, bindings, keyframes);\n\n// after\nvar keyframes = clipData.HasKeyframes ? BuildKeyframes() : Array.Empty<ObjectReferenceKeyframe[]>();\nAnimationUtility.SetObjectReferenceCurves(clip, bindings, keyframes);","handlingStrategy":"validation","validationCode":"if (keyframes == null) keyframes = Array.Empty<ObjectReferenceKeyframe[]>();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember the plural API forbids null keyframes even though the singular API allows null to delete.","Default jagged keyframe arrays to empty rather than null.","Round-trip serialization must distinguish empty vs absent."],"tags":["animation","argument-null","editor","csharp"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}