Unity-Technologies/UnityCsReference · error · ArgumentNullException

keyframes must be non-null

Error message

keyframes must be non-null

What it means

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.

Source

Thrown at Editor/Mono/Animation/AnimationUtility.bindings.cs:247

        extern internal static PropertyModification EditorCurveBindingToPropertyModification(EditorCurveBinding binding, [NotNull] GameObject gameObject);

        extern public static EditorCurveBinding[] GetCurveBindings([NotNull] AnimationClip clip);
        extern public static EditorCurveBinding[] GetObjectReferenceCurveBindings([NotNull] AnimationClip clip);

        extern public static ObjectReferenceKeyframe[] GetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding);

        public static void SetObjectReferenceCurve(AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes)
        {
            Internal_SetObjectReferenceCurve(clip, binding, keyframes, true);
            Internal_InvokeOnCurveWasModified(clip, binding, keyframes != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);
        }

        public static void SetObjectReferenceCurves(AnimationClip clip, EditorCurveBinding[] bindings, ObjectReferenceKeyframe[][] keyframes)
        {
            if (bindings == null)
                throw new ArgumentNullException(nameof(bindings), $"{nameof(bindings)} must be non-null");
            if (keyframes == null)
                throw new ArgumentNullException(nameof(keyframes), $"{nameof(keyframes)} must be non-null");
            if (bindings.Length != keyframes.Length)
                throw new InvalidOperationException($"{nameof(bindings)} and {nameof(keyframes)} must be of equal length");

            int length = bindings.Length;
            for (int i = 0; i < length; i++)
            {
                SetObjectReferenceCurveNoSync(clip, bindings[i], keyframes[i]);
            }
            SyncEditorCurves(clip);
            Internal_InvokeOnCurveWasModified(clip, new EditorCurveBinding(), CurveModifiedType.ClipModified);
        }

        internal static void SetObjectReferenceCurveNoSync(AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes)
        {
            Internal_SetObjectReferenceCurve(clip, binding, keyframes, false);
            Internal_InvokeOnCurveWasModified(clip, binding, keyframes != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);
        }

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Default keyframes to an empty jagged array when there is nothing to write.
  2. Build keyframes to exactly mirror bindings length, element for element.
  3. Map a null result to Array.Empty<ObjectReferenceKeyframe[]>() at the boundary.
  4. If you intend to delete all curves, call SetObjectReferenceCurve per binding with null instead of the batch API.

Example fix

// before
var keyframes = clipData.HasKeyframes ? BuildKeyframes() : null;
AnimationUtility.SetObjectReferenceCurves(clip, bindings, keyframes);

// after
var keyframes = clipData.HasKeyframes ? BuildKeyframes() : Array.Empty<ObjectReferenceKeyframe[]>();
AnimationUtility.SetObjectReferenceCurves(clip, bindings, keyframes);
Defensive patterns

Strategy: validation

Validate before calling

if (keyframes == null) keyframes = Array.Empty<ObjectReferenceKeyframe[]>();

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/92a24688438b329f. Report an issue: GitHub.