spectreconsole/spectre.console · error · InvalidOperationException
Invalid RGB color '{rgb}'. {ex.Message}
Error message
Invalid RGB color '{rgb}'. {ex.Message} What it means
ParseRgbColor caught an exception converting the component strings to bytes (e.g. non-numeric, out-of-byte-range overflow). The inner exception message is appended, e.g. for `[rgb(255,a,0)]` or `[rgb(300,0,0)]`.
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
- Use three integer components each in 0-255, e.g. rgb(255,128,0)
- Clamp and round floats: (byte)Math.Round(Math.Clamp(v,0,255))
- Validate with a regex like ^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$
Example fix
// before
AnsiMarkup.Parse("[rgb(255,a,0)]text[/]");
// after
AnsiMarkup.Parse("[rgb(255,160,0)]text[/]"); Defensive patterns
Strategy: validation
Validate before calling
public static bool IsValidRgb(string token)
{
var m = Regex.Match(token, @"^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$");
return m.Success && m.Groups.Cast<Group>().Skip(1).All(g => int.Parse(g.Value) is >= 0 and <= 255);
} Try / catch
try { AnsiMarkup.Parse(markup); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Invalid RGB color"))
{ /* clamp components to 0-255 and rebuild as rgb(r,g,b) */ } Prevention
- Use integer components in 0-255 only (no %, no decimals)
- Clamp float values before converting to byte
- Prefer #rrggbb for generated colors to sidestep rgb() parsing
When it happens
Trigger: An `rgb(...)` part whose components aren't parseable bytes: non-numeric characters, or values outside 0-255 that overflow Convert.ToInt32→byte cast.
Common situations: Feeding floating-point or percentage values like `rgb(50%,50%,50%)`; values >255 from unclamped math; localized decimal separators.
Related errors
- Invalid RGB color '{rgb}'.
- Color number must be greater than or equal to 0 (was {number
- Color number must be less than or equal to 255 (was {number}
- Could not find color '{part}'.
- Could not find color or style '{part}'.
AI-assisted analysis of spectreconsole/spectre.console@0acc92fada (2026-08-13).
Data as JSON: /api/errors/003efc6d16f19933.
Report an issue: GitHub.