Unity-Technologies/UnityCsReference · error · ArgumentNullException

bindings must be non-null

Error message

bindings must be non-null

What it means

Thrown by AnimationUtility.SetObjectReferenceCurves when the bindings array is null. The method zips bindings with keyframes element-wise; a null bindings array has no Length to compare against keyframes.Length and no elements to loop. The guard uses nameof for a precise paramName and runs before any native call.

Source

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

        extern private static Type Internal_PropertyModificationToEditorCurveBinding(PropertyModification modification, [NotNull] GameObject gameObject, out EditorCurveBinding binding);
        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. Construct bindings with an explicit empty array fallback: bindings ?? Array.Empty<EditorCurveBinding>().
  2. Ensure bindings and keyframes are built in the same method with the same count.
  3. Validate both arrays (null + length) in a shared helper before all Set*Curves calls.
  4. If bindings are optional, early-return instead of calling with null.

Example fix

// before
AnimationUtility.SetObjectReferenceCurves(clip, bindings, keyframes);

// after
bindings ??= Array.Empty<EditorCurveBinding>();
keyframes ??= Array.Empty<ObjectReferenceKeyframe[]>();
if (bindings.Length == 0) return;
AnimationUtility.SetObjectReferenceCurves(clip, bindings, keyframes);
Defensive patterns

Strategy: validation

Validate before calling

if (bindings == null || bindings.Length == 0) return;

Type guard

static bool HasBindings(EditorCurveBinding[] b) => b != null && b.Length > 0;

Prevention

When it happens

Trigger: Calling SetObjectReferenceCurves(clip, null, keyframes). Building the EditorCurveBinding[] from a LINQ query that returned null (rare, but possible from a custom collector returning null instead of empty). Reusing a stale field that was never initialized.

Common situations: Animation clip importers/post-processors that assemble object reference curves programmatically. Timeline tooling that deserializes binding lists from JSON where bindings was absent. Editor extensions syncing curves across clips.

Related errors


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