iOfficeAI/OfficeCLI · error · ArgumentException

gradientFill requires at least two '-' separated colors; got

Error message

gradientFill requires at least two '-' separated colors; got '{spec}'.

What it means

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.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Helpers.Drawing.cs:302

    internal static Drawing.GradientFill BuildShapeGradientFill(string spec)
    {
        var colonIdx = spec.LastIndexOf(':');
        var anglePart = 0;
        string colorsPart;
        if (colonIdx > 6 && int.TryParse(spec[(colonIdx + 1)..],
            System.Globalization.NumberStyles.Integer,
            System.Globalization.CultureInfo.InvariantCulture, out var ang))
        {
            anglePart = ang;
            colorsPart = spec[..colonIdx];
        }
        else
        {
            colorsPart = spec;
        }
        var colors = colorsPart.Split('-').Select(c => c.Trim()).Where(c => c.Length > 0).ToArray();
        if (colors.Length < 2)
            throw new ArgumentException(
                $"gradientFill requires at least two '-' separated colors; got '{spec}'.");
        var gradFill = new Drawing.GradientFill { RotateWithShape = true };
        var gsLst = new Drawing.GradientStopList();
        for (int i = 0; i < colors.Length; i++)
        {
            var pos = (int)(i * 100000.0 / (colors.Length - 1));
            var (rgb, _) = ParseHelpers.SanitizeColorForOoxml(colors[i]);
            var gs = new Drawing.GradientStop { Position = pos };
            gs.AppendChild(new Drawing.RgbColorModelHex { Val = rgb });
            gsLst.AppendChild(gs);
        }
        gradFill.AppendChild(gsLst);
        gradFill.AppendChild(new Drawing.LinearGradientFill
        {
            Angle = ParseHelpers.GradientAngleToOoxmlUnits(anglePart),
            Scaled = true
        });
        return gradFill;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Pass at least two dash-separated colors, e.g. gradientFill='FF0000-0000FF' for a red-to-blue gradient.
  2. Add a third stop if needed: gradientFill='FF0000-FFFF00-0000FF', and an optional angle after a colon: gradientFill='FF0000-0000FF:45'.
  3. If you want a solid fill, use the solid fill property (fill=...) instead of gradientFill.
  4. Use hex (RRGGBB) or the named colors accepted by ParseHelpers.SanitizeColorForOoxml; verify each color token individually if the spec still fails.

Example fix

// before
shape fill=gradientFill:"red"
// after
shape fill=gradientFill:"FF0000-0000FF"
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidGradientSpec(string spec)
{
    if (string.IsNullOrWhiteSpace(spec)) return false;
    var colonIdx = spec.LastIndexOf(':');
    var colorsPart = colonIdx > 6 ? spec[..colonIdx] : spec;
    var colors = colorsPart.Split('-')
        .Select(c => c.Trim())
        .Where(c => c.Length > 0)
        .ToArray();
    return colors.Length >= 2;
}

// call before BuildShapeGradientFill:
if (!IsValidGradientSpec(spec))
    throw new InvalidOperationException($"gradientFill spec '{spec}' needs >=2 dash-separated colors.");

Type guard

static bool IsGradientFillSpec(string spec)
    => !string.IsNullOrWhiteSpace(spec)
       && (spec.LastIndexOf(':') > 6 ? spec[..spec.LastIndexOf(':')] : spec)
           .Split('-').Select(s => s.Trim()).Count(s => s.Length > 0) >= 2;

Try / catch

try { var fill = BuildShapeGradientFill(spec); }
catch (ArgumentException ex) when (ex.Message.Contains("gradientFill requires"))
{
    // log and fall back to a solid fill or surface a user-facing error
}

Prevention

When it happens

Trigger: 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='-'.

Common situations: 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.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/91106a3c997a0b65. Report an issue: GitHub.