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
- Clamp the color index to the 0-255 range before embedding it in markup
- Use a named color or `#rrggbb`/`rgb(...)` form instead of a raw index
- 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
- Validate numeric color indices against 0-255 at the source
- Prefer named colors or true-color hex when the value is computed
- Use Math.Clamp as a cheap safety net
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
- Color number must be less than or equal to 255 (was {number}
- Could not find color '{part}'.
- Could not find color or style '{part}'.
- A foreground color has already been set.
- A background color has already been set.
AI-assisted analysis of spectreconsole/spectre.console@0acc92fada (2026-08-13).
Data as JSON: /api/errors/5ea7224eeadb5bb8.
Report an issue: GitHub.