{"record":{"id":"91106a3c997a0b65","repo":"iOfficeAI/OfficeCLI","slug":"gradientfill-requires-at-least-two-separated-c","errorCode":null,"errorMessage":"gradientFill requires at least two '-' separated colors; got '{spec}'.","messagePattern":"gradientFill requires at least two '-' separated colors; got '(.+?)'\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Helpers.Drawing.cs","lineNumber":302,"sourceCode":"    internal static Drawing.GradientFill BuildShapeGradientFill(string spec)\n    {\n        var colonIdx = spec.LastIndexOf(':');\n        var anglePart = 0;\n        string colorsPart;\n        if (colonIdx > 6 && int.TryParse(spec[(colonIdx + 1)..],\n            System.Globalization.NumberStyles.Integer,\n            System.Globalization.CultureInfo.InvariantCulture, out var ang))\n        {\n            anglePart = ang;\n            colorsPart = spec[..colonIdx];\n        }\n        else\n        {\n            colorsPart = spec;\n        }\n        var colors = colorsPart.Split('-').Select(c => c.Trim()).Where(c => c.Length > 0).ToArray();\n        if (colors.Length < 2)\n            throw new ArgumentException(\n                $\"gradientFill requires at least two '-' separated colors; got '{spec}'.\");\n        var gradFill = new Drawing.GradientFill { RotateWithShape = true };\n        var gsLst = new Drawing.GradientStopList();\n        for (int i = 0; i < colors.Length; i++)\n        {\n            var pos = (int)(i * 100000.0 / (colors.Length - 1));\n            var (rgb, _) = ParseHelpers.SanitizeColorForOoxml(colors[i]);\n            var gs = new Drawing.GradientStop { Position = pos };\n            gs.AppendChild(new Drawing.RgbColorModelHex { Val = rgb });\n            gsLst.AppendChild(gs);\n        }\n        gradFill.AppendChild(gsLst);\n        gradFill.AppendChild(new Drawing.LinearGradientFill\n        {\n            Angle = ParseHelpers.GradientAngleToOoxmlUnits(anglePart),\n            Scaled = true\n        });\n        return gradFill;","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Helpers.Drawing.cs#L284-L320","documentation":"Thrown by BuildShapeGradientFill when parsing a 'C1-C2[-C3][:angle]' gradient spec for a shape/textbox fill. The parser splits the color portion on '-' and requires at least two non-empty color tokens; a spec with zero or one color cannot form a gradient (Excel needs a gradient stop list of >=2). The angle suffix is only honored when the ':' sits past index 6, so short single-color specs never accidentally consume a color as an angle.","triggerScenarios":"Calling the shape/textbox fill path with gradientFill='FF0000' (single hex, no dash), gradientFill='red' (single named color), gradientFill='' (empty), or gradientFill='red blue' (space-separated instead of dash-separated). Also triggered when the spec contains only a dash with empty sides like gradientFill='-'.","commonSituations":"Treating gradientFill as a solid-color property (passing one color); copying CSS 'linear-gradient(red, blue)' syntax verbatim (commas/spaces instead of dashes); AI assistants emitting a single hex when the user asked for a 'red gradient'; trailing/leading dashes that split to empty tokens that get filtered out.","solutions":["Pass at least two dash-separated colors, e.g. gradientFill='FF0000-0000FF' for a red-to-blue gradient.","Add a third stop if needed: gradientFill='FF0000-FFFF00-0000FF', and an optional angle after a colon: gradientFill='FF0000-0000FF:45'.","If you want a solid fill, use the solid fill property (fill=...) instead of gradientFill.","Use hex (RRGGBB) or the named colors accepted by ParseHelpers.SanitizeColorForOoxml; verify each color token individually if the spec still fails."],"exampleFix":"// before\nshape fill=gradientFill:\"red\"\n// after\nshape fill=gradientFill:\"FF0000-0000FF\"","handlingStrategy":"validation","validationCode":"bool IsValidGradientSpec(string spec)\n{\n    if (string.IsNullOrWhiteSpace(spec)) return false;\n    var colonIdx = spec.LastIndexOf(':');\n    var colorsPart = colonIdx > 6 ? spec[..colonIdx] : spec;\n    var colors = colorsPart.Split('-')\n        .Select(c => c.Trim())\n        .Where(c => c.Length > 0)\n        .ToArray();\n    return colors.Length >= 2;\n}\n\n// call before BuildShapeGradientFill:\nif (!IsValidGradientSpec(spec))\n    throw new InvalidOperationException($\"gradientFill spec '{spec}' needs >=2 dash-separated colors.\");","typeGuard":"static bool IsGradientFillSpec(string spec)\n    => !string.IsNullOrWhiteSpace(spec)\n       && (spec.LastIndexOf(':') > 6 ? spec[..spec.LastIndexOf(':')] : spec)\n           .Split('-').Select(s => s.Trim()).Count(s => s.Length > 0) >= 2;","tryCatchPattern":"try { var fill = BuildShapeGradientFill(spec); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"gradientFill requires\"))\n{\n    // log and fall back to a solid fill or surface a user-facing error\n}","preventionTips":["Always include at least two dash-separated colors (e.g. 'FF0000-0000FF').","Use hex RRGGBB or the named colors accepted by SanitizeColorForOoxml.","Do not use commas or spaces between colors - only dashes.","Validate the spec shape before calling if sourcing from user input."],"tags":["excel","drawing","shape","gradient","validation","fill"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}