spectreconsole/spectre.console · error · InvalidOperationException

Color number must be greater than or equal to 0 (was {number

Error message

Color number must be greater than or equal to 0 (was {number})

What it means

In AnsiMarkupTagParser.Parse, a tag part parses as an integer (so it is treated as a 256-palette color index) but the value is negative. Color indices must be 0-255; the offending number is interpolated into the message.

Source

Thrown at src/Spectre.Console.Ansi/AnsiMarkupTagParser.cs:10

namespace Spectre.Console;

internal static class AnsiMarkupTagParser
{
    public static (Style Style, Link? Link) Parse(string text)
    {
        var result = Parse(text, out var error);
        if (error != null)
        {
            throw new InvalidOperationException(error);
        }

        return result ?? throw new InvalidOperationException("Could not parse style.");
    }

    public static bool TryParse(string text, [NotNullWhen(true)] out (Style Style, Link?)? result)
    {
        result = Parse(text, out _);
        return result != null;
    }

    private static (Style Style, Link? Link)? Parse(string text, out string? error)
    {
        var effectiveDecoration = (Decoration?)null;
        var effectiveForeground = (Color?)null;
        var effectiveBackground = (Color?)null;
        var effectiveLink = (string?)null;

View on GitHub (pinned to 0acc92fada)

Solutions

  1. Clamp the color index to the 0-255 range before embedding it in markup
  2. Use a named color or `#rrggbb`/`rgb(...)` form instead of a raw index
  3. Validate generated indices against 0-255

Example fix

// before
AnsiMarkup.Parse($"[{computedIndex}]text[/]"); // computedIndex may be -1

// after
var safe = Math.Clamp(computedIndex, 0, 255);
AnsiMarkup.Parse($"[{safe}]text[/]");
Defensive patterns

Strategy: validation

Validate before calling

// Clamp any numeric color index into range before building markup:
int safeIndex = Math.Clamp(rawIndex, 0, 255);
var markup = $"[{safeIndex}]text[/]";

Try / catch

try { AnsiMarkup.Parse(markup); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Color number must be greater than or equal to 0"))
{ /* re-clamp and retry with index 0 */ }

Prevention

When it happens

Trigger: A tag like `[on -1]`, `[red -5]`, or any markup tag containing a bare negative integer in a color position.

Common situations: Off-by-one or sign error in code generating a color index; arithmetic that produces a negative value fed into a markup tag.

Related errors


AI-assisted analysis of spectreconsole/spectre.console@0acc92fada (2026-08-13). Data as JSON: /api/errors/5ea7224eeadb5bb8. Report an issue: GitHub.