{"record":{"id":"f9fa0e7645dae19a","repo":"AvaloniaUI/Avalonia","slug":"invalid-keyspline-x2-value-must-be-0-0-and","errorCode":null,"errorMessage":"Invalid KeySpline X2 value. Must be >= 0.0 and <= 1.0.","messagePattern":"Invalid KeySpline X2 value\\. Must be >= 0\\.0 and <= 1\\.0\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Animation/KeySpline.cs","lineNumber":138,"sourceCode":"            }\n        }\n\n        /// <summary>\n        /// X coordinate of the second control point\n        /// </summary>\n        public double ControlPointX2\n        {\n            get => _controlPointX2;\n            set\n            {\n                if (IsValidXValue(value))\n                {\n                    _controlPointX2 = value;\n                    _isDirty = true;\n                }\n                else\n                {\n                    throw new ArgumentException(\"Invalid KeySpline X2 value. Must be >= 0.0 and <= 1.0.\");\n                }\n            }\n        }\n\n        /// <summary>\n        /// Y coordinate of the second control point\n        /// </summary>\n        public double ControlPointY2\n        {\n            get => _controlPointY2;\n            set\n            {\n                _controlPointY2 = value;\n                _isDirty = true;\n            }\n        }\n\n        /// <summary>","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Animation/KeySpline.cs#L120-L156","documentation":"Thrown by the ControlPointX2 setter when the supplied X2 value fails IsValidXValue (outside [0.0, 1.0]). Symmetric to the X1 case: the second control point's X must also stay normalized because it anchors the right side of the easing bezier's time axis.","triggerScenarios":"Assigning a number outside [0,1] to KeySpline.ControlPointX2; building a curve like (0,0,2,1) where the second point's X overshoots.","commonSituations":"Mistakenly believing X2 can exceed 1 to model overshoot (overshoot is expressed via Y, not X); copy-pasting CSS cubic-bezier tuples with the wrong column.","solutions":["Keep ControlPointX2 within 0.0 and 1.0 inclusive.","Clamp before assignment: Math.Clamp(v, 0.0, 1.0).","Express overshoot/bounce through Y1/Y2, not X2."],"exampleFix":"// before\nspline.ControlPointX2 = 2.0;\n\n// after\nspline.ControlPointX2 = 1.0;","handlingStrategy":"validation","validationCode":"double x2 = Math.Clamp(rawX2, 0.0, 1.0);\nspline.ControlPointX2 = x2;","typeGuard":"static bool IsValidX(double v) => double.IsFinite(v) && v >= 0.0 && v <= 1.0;","tryCatchPattern":"try { spline.ControlPointX2 = v; }\ncatch (ArgumentException) { spline.ControlPointX2 = Math.Clamp(v, 0.0, 1.0); }","preventionTips":["Clamp X2 just like X1.","Express overshoot via Y2, never X2."],"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"}