{"record":{"id":"33f47b761412ecdf","repo":"AvaloniaUI/Avalonia","slug":"nameof-keyspline-must-have-x-coordinates-0-0","errorCode":null,"errorMessage":"{nameof(KeySpline)} must have X coordinates >= 0.0 and <= 1.0.","messagePattern":"(.+?) must have X coordinates >= 0\\.0 and <= 1\\.0\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Animation/KeyFrame.cs","lineNumber":94,"sourceCode":"            }\n        }\n\n        /// <summary>\n        /// Gets or sets the KeySpline of this <see cref=\"KeyFrame\"/>.\n        /// </summary>\n        /// <value>The key spline.</value>\n        public KeySpline? KeySpline\n        {\n            get\n            {\n                return _kKeySpline;\n            }\n            set\n            {\n                _kKeySpline = value;\n                if (value != null && !value.IsValid())\n                {\n                    throw new ArgumentException($\"{nameof(KeySpline)} must have X coordinates >= 0.0 and <= 1.0.\");\n                }\n            }\n        }\n\n        internal override void BuildDebugDisplay(StringBuilder builder, bool includeContent)\n        {\n            base.BuildDebugDisplay(builder, includeContent);\n\n            switch (TimingMode)\n            {\n                case KeyFrameTimingMode.TimeSpan:\n                    DebugDisplayHelper.AppendOptionalValue(builder, nameof(KeyTime), KeyTime, includeContent);\n                    break;\n                case KeyFrameTimingMode.Cue:\n                    DebugDisplayHelper.AppendOptionalValue(builder, nameof(Cue), Cue, includeContent);\n                    break;\n            }\n        }","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Animation/KeyFrame.cs#L76-L112","documentation":"Thrown when assigning a KeySpline to a KeyFrame whose X control coordinates are outside the [0.0, 1.0] range. A KeySpline models a cubic-bezier easing curve where the X axis is normalized time, so X must stay in [0,1]; Y is unconstrained. The setter stores the value first, then calls IsValid() (which only checks X1 and X2) and throws on failure.","triggerScenarios":"Setting KeyFrame.KeySpline to a KeySpline instance constructed or mutated with ControlPointX1 or ControlPointX2 outside [0,1]; or parsing a KeySpline string like \"1.5,0,0.5,1\" and assigning it to a key frame.","commonSituations":"Hand-typing an easing curve in XAML or code-behind and overshooting an X coordinate; importing WPF/CSS cubic-bezier values without clamping; confusing the X (time) and Y (progress) axes.","solutions":["Ensure ControlPointX1 and ControlPointX2 are both within 0.0 and 1.0 inclusive.","If you only want to shape progress, vary Y1/Y2 and keep X1/X2 in range (e.g. use 0.42,0,0.58,1 for ease-in-out).","Call keySpline.IsValid() yourself before assigning it to KeyFrame.KeySpline to get a clean boolean."],"exampleFix":"// before\nframe.KeySpline = new KeySpline(1.5, 0.0, 0.5, 1.0); // X1=1.5 out of range\n\n// after\nframe.KeySpline = new KeySpline(0.42, 0.0, 0.58, 1.0);","handlingStrategy":"validation","validationCode":"static bool TrySetKeySpline(KeyFrame frame, KeySpline spline)\n{\n    if (spline is null || !spline.IsValid()) return false;\n    frame.KeySpline = spline;\n    return true;\n}","typeGuard":"static bool IsValidKeySpline(KeySpline? s) =>\n    s is not null && s.ControlPointX1 >= 0.0 && s.ControlPointX1 <= 1.0\n                  && s.ControlPointX2 >= 0.0 && s.ControlPointX2 <= 1.0;","tryCatchPattern":"try { frame.KeySpline = spline; }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"X coordinates\"))\n{ /* log and clamp or fall back to a known-good spline */ }","preventionTips":["Always construct KeySpline from validated numeric inputs (Math.Clamp on X).","Unit-test easing-curve definitions against IsValid().","Keep X1/X2 in [0,1] and only vary Y when shaping curves."],"tags":["animation","keyspline","validation","argument"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}