iOfficeAI/OfficeCLI · error · ArgumentException
Invalid color value: '{original}'. HSL saturation/lightness
Error message
Invalid color value: '{original}'. HSL saturation/lightness must be 0%-100%. What it means
Thrown by ParsePercent01 when an HSL saturation or lightness percentage parses as a number but is outside 0%-100%. Both channels are clamped-free in CSS terms here — the library rejects out-of-range rather than silently clipping, to surface bad color math.
Source
Thrown at src/officecli/Core/ParseHelpers.cs:213
// — turn/rad/grad — are out of scope for the input vocabulary we care
// about and would just need their own multipliers if asked for).
if (token.EndsWith("deg", StringComparison.OrdinalIgnoreCase))
token = token[..^3].Trim();
if (!double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var h))
throw new ArgumentException($"Invalid color value: '{original}'. Hue must be a number in degrees.");
h %= 360;
if (h < 0) h += 360;
return h;
}
private static double ParsePercent01(string token, string original)
{
token = token.Trim();
if (!token.EndsWith('%'))
throw new ArgumentException($"Invalid color value: '{original}'. HSL saturation/lightness must be expressed as a percentage (e.g. 50%).");
if (!double.TryParse(token[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out var pct)
|| pct < 0 || pct > 100)
throw new ArgumentException($"Invalid color value: '{original}'. HSL saturation/lightness must be 0%-100%.");
return pct / 100.0;
}
private static (byte R, byte G, byte B) HslToRgb(double h, double s, double l)
{
// Standard HSL → RGB (CSS Color Module Level 3).
double c = (1 - Math.Abs(2 * l - 1)) * s;
double hp = h / 60.0;
double x = c * (1 - Math.Abs(hp % 2 - 1));
double r1 = 0, g1 = 0, b1 = 0;
if (hp < 1) { r1 = c; g1 = x; b1 = 0; }
else if (hp < 2) { r1 = x; g1 = c; b1 = 0; }
else if (hp < 3) { r1 = 0; g1 = c; b1 = x; }
else if (hp < 4) { r1 = 0; g1 = x; b1 = c; }
else if (hp < 5) { r1 = x; g1 = 0; b1 = c; }
else { r1 = c; g1 = 0; b1 = x; }
double m = l - c / 2;
return (View on GitHub (pinned to 1ced45e900)
Solutions
- Clamp S and L to [0,100] before formatting.
- Audit color-space conversion code for unbounded outputs.
- Round and clamp in one step: Math.Clamp(Math.Round(v),0,100).
Example fix
// before
var c = $"hsl({h},{s}%,{l}%"); // s == 150
ParseColor(c); // throws 290
// after
int C(double v) => (int)Math.Clamp(Math.Round(v),0,100);
var c = $"hsl({h},{C(s)}%,{C(l)}%)");
ParseColor(c); Defensive patterns
Strategy: validation
Validate before calling
static string ClampSl(double v) => $"{Math.Clamp(Math.Round(v),0,100)}%";
// build: $"hsl({h},{ClampSl(s)},{ClampSl(l)})" Type guard
static bool IsValidSlPct(string token)
=> token.EndsWith('%')
&& double.TryParse(token[..^1], CultureInfo.InvariantCulture, out var v)
&& v >= 0 && v <= 100; Try / catch
try { color = ParseColor(spec); }
catch (ArgumentException ex) when (ex.Message.Contains("must be 0%-100%"))
{ /* clamp S/L and retry */ } Prevention
- Clamp HSL S/L to [0,100]% after any color math.
- Audit color-space conversions for out-of-gamut outputs.
- Round and clamp in one step to avoid drift.
When it happens
Trigger: Passing hsl(120,150%,50%) or hsl(120,50%,-10%). A saturation/lightness computed from a gradient or blend that exceeded bounds.
Common situations: HSL manipulation code that adds saturation without clamping; UI sliders allowing >100%; converting from another color space whose gamut exceeds HSL.
Related errors
- Invalid color value: '{original}'. RGB percentage components
- Invalid color value: '{original}'. RGB components must be 0-
- Invalid color value: '{original}'. Alpha percentage must be
- Invalid color value: '{original}'. Alpha must be 0-1 (e.g. 0
- Invalid color value: '{original}'. Hue must be a number in d
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/10165ae32773a3ef.
Report an issue: GitHub.