iOfficeAI/OfficeCLI · error · ArgumentException

Invalid threshold '{parts[0]}' in colorRule. Expected a numb

Error message

Invalid threshold '{parts[0]}' in colorRule. Expected a number.

What it means

In the simple 3-part colorRule form (threshold:belowColor:aboveColor), parts[0] must be a numeric threshold. If double.TryParse fails on the first segment, the library rejects it with 'Expected a number'. This is the 3-part path specifically (parts.Length == 3); the multi-zone path has its own error (error 129).

Source

Thrown at src/officecli/Core/Chart/ChartHelper.Advanced.cs:311

    /// Three-tier: "0:FF0000:50:FFAA00:100:00AA00" — red/orange/green zones
    /// </summary>
    internal static void ApplyColorRule(C.PlotArea plotArea, string spec)
    {
        var parts = spec.Split(':');
        if (parts.Length < 3)
            throw new ArgumentException(
                $"Invalid colorRule '{spec}'. Expected: threshold:belowColor:aboveColor (e.g. '0:FF0000:00AA00') " +
                "or low:lowColor:mid:midColor:high:highColor (e.g. '0:FF0000:50:FFAA00:100:00AA00').");

        var rules = new List<(double threshold, string color)>();
        string topColor;

        if (parts.Length == 3)
        {
            // Simple two-zone: threshold:belowColor:aboveColor
            if (!double.TryParse(parts[0], System.Globalization.NumberStyles.Float,
                System.Globalization.CultureInfo.InvariantCulture, out var t))
                throw new ArgumentException($"Invalid threshold '{parts[0]}' in colorRule. Expected a number.");
            rules.Add((t, parts[1].Trim()));
            topColor = parts[2].Trim();
        }
        else
        {
            // Multi-zone: t1:c1:t2:c2:...:cN
            for (int i = 0; i < parts.Length - 1; i += 2)
            {
                if (!double.TryParse(parts[i], System.Globalization.NumberStyles.Float,
                    System.Globalization.CultureInfo.InvariantCulture, out var t))
                    throw new ArgumentException($"Invalid threshold '{parts[i]}' in colorRule.");
                rules.Add((t, parts[i + 1].Trim()));
            }
            topColor = parts.Length % 2 == 1 ? parts[^1].Trim() : rules[^1].color;
            if (parts.Length % 2 == 0)
                rules.RemoveAt(rules.Count - 1); // Last pair has no "above" — use as topColor
        }

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Ensure the first segment in a 3-part colorRule is a plain number: '0:FF0000:00AA00'.
  2. Use a dot as the decimal separator: '0.5' not '0,5'.
  3. Use numeric values only — the library does not compute aggregates like average or median.

Example fix

// before
colorrule: "abc:FF0000:00AA00"
// after
colorrule: "0:FF0000:00AA00"
Defensive patterns

Strategy: validation

Validate before calling

static bool IsThresholdNumeric3Part(string spec)
{
    var parts = spec.Split(':');
    return parts.Length != 3 || double.TryParse(parts[0],
        System.Globalization.NumberStyles.Float,
        System.Globalization.CultureInfo.InvariantCulture, out _);
}

Try / catch

try { ChartHelperAdvanced.ApplyColorRule(plotArea, spec); }
catch (ArgumentException ex) when (ex.Message.Contains("Invalid threshold") && ex.Message.Contains("Expected a number"))
{
    Console.Error.WriteLine($"Threshold in 3-part colorRule is non-numeric. Use a plain number.");
}

Prevention

When it happens

Trigger: Passing a 3-part colorRule where the first segment is non-numeric: 'abc:FF0000:00AA00' or 'N/A:FF0000:00AA00'. The spec must have exactly 3 colon-separated parts.

Common situations: Using locale-specific number formats with comma decimals ('0,5:FF0000:00AA00'). Placing a color in the threshold slot by mistake. Using a non-numeric sentinel like 'avg' or 'median' (not supported — only literal numbers).

Related errors


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