Unity-Technologies/UnityCsReference · error · ArgumentNullException
curves must be non-null
Error message
curves must be non-null
What it means
Thrown by AnimationUtility.SetEditorCurves when the curves array (AnimationCurve[]) is null. Singular SetEditorCurve accepts a null curve to delete that binding, but the batch form requires a non-null array so it can compare length with bindings and iterate. Guard order: bindings null, then curves null, then length mismatch.
Source
Thrown at Editor/Mono/Animation/AnimationUtility.bindings.cs:282
}
[NativeMethod(ThrowsException = true)]
extern private static void Internal_SetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes, bool updateMuscleClip);
extern public static AnimationCurve GetEditorCurve([NotNull] AnimationClip clip, EditorCurveBinding binding);
public static void SetEditorCurve(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve)
{
Internal_SetEditorCurve(clip, binding, curve, true);
Internal_InvokeOnCurveWasModified(clip, binding, curve != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);
}
public static void SetEditorCurves(AnimationClip clip, EditorCurveBinding[] bindings, AnimationCurve[] curves)
{
if (bindings == null)
throw new ArgumentNullException(nameof(bindings), $"{nameof(bindings)} must be non-null");
if (curves == null)
throw new ArgumentNullException(nameof(curves), $"{nameof(curves)} must be non-null");
if (bindings.Length != curves.Length)
throw new InvalidOperationException($"{nameof(bindings)} and {nameof(curves)} must be of equal length");
int length = bindings.Length;
for (int i = 0; i < length; i++)
{
SetEditorCurveNoSync(clip, bindings[i], curves[i]);
}
SyncEditorCurves(clip);
Internal_InvokeOnCurveWasModified(clip, new EditorCurveBinding(), AnimationUtility.CurveModifiedType.ClipModified);
}
internal static void SetEditorCurveNoSync(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve)
{
Internal_SetEditorCurve(clip, binding, curve, false);
Internal_InvokeOnCurveWasModified(clip, binding, curve != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted);
}View on GitHub (pinned to 225b0fbdb5)
Solutions
- Default to Array.Empty<AnimationCurve>() instead of null when no curves exist.
- If you mean to delete curves, pass non-null array of nulls (one per binding) or use the singular API per binding.
- Build curves and bindings in one pass.
- Validate at the boundary before calling.
Example fix
// before var curves = hasData ? BuildCurves() : null; AnimationUtility.SetEditorCurves(clip, bindings, curves); // after var curves = hasData ? BuildCurves() : Array.Empty<AnimationCurve>(); AnimationUtility.SetEditorCurves(clip, bindings, curves);
Defensive patterns
Strategy: validation
Validate before calling
if (curves == null) curves = Array.Empty<AnimationCurve>();
Prevention
- Do not reuse the singular SetEditorCurve null-means-delete semantics in the batch API.
- Default curve arrays to empty, not null.
- To delete via batch, pass a non-null array of nulls matching bindings length.
When it happens
Trigger: Calling SetEditorCurves(clip, bindings, null). A curve builder that returns null for 'no curves'. Reusing the singular API's null-means-delete semantics in the plural API.
Common situations: Programmatic clip generation defaulting curves to null. Serialization round-trips where an empty curves array came back as null. Copying from SetEditorCurve singular usage.
Related errors
- gameObject
- bindings must be non-null
- keyframes must be non-null
- list
- Value for parameter atlases is null
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/275cb408ded9980b.
Report an issue: GitHub.