iOfficeAI/OfficeCLI · warning · ArgumentException
Unknown color transform '{name}'. Valid: lumMod, lumOff, sha
Error message
Unknown color transform '{name}'. Valid: lumMod, lumOff, shade, tint, satMod, satOff, hueMod, hueOff, alpha. What it means
ParseColorTransformSuffix scans each token's leading letter run as the transform name and checks it against KnownTransforms ({lumMod, lumOff, shade, tint, satMod, satOff, hueMod, hueOff, alpha}, case-insensitive). An unrecognized name is rejected rather than silently dropped, so a typo doesn't produce a no-op color. The valid set is listed in the message.
Source
Thrown at src/officecli/Core/DrawingColorBuilder.cs:114
{
var result = new List<(string Name, int Val)>();
foreach (var token in chain.Split('+', StringSplitOptions.RemoveEmptyEntries))
{
// Two accepted forms:
// "lumMod75" — Get's canonical round-trip form, percent 0..100
// "lumMod=75000" — raw OOXML percentage 0..100000
// (matches the literal a:lumMod@val attribute,
// what users see in PowerPoint XML / docs)
// Both end up encoded as @val="75000" on the OOXML child. The name is
// a leading run of letters; the remainder is '='?<signed-int>. Scan the
// name by letters (not "first digit") so a leading '-' on the value
// stays with the value instead of being folded into the name.
int i = 0;
while (i < token.Length && char.IsLetter(token[i])) i++;
if (i == 0 || i == token.Length) continue;
var name = token.Substring(0, i);
if (!KnownTransforms.Contains(name))
throw new ArgumentException(
$"Unknown color transform '{name}'. Valid: lumMod, lumOff, shade, tint, satMod, satOff, hueMod, hueOff, alpha.");
bool eqForm = token[i] == '=';
string numText = eqForm ? token.Substring(i + 1) : token.Substring(i);
if (!int.TryParse(numText, out var raw))
throw new ArgumentException(
$"Invalid color transform '{token}': value must be an integer.");
// OOXML splits the transforms into two schema types:
// shade / tint / alpha → ST_PositiveFixedPercentage (0..100%),
// negatives forbidden.
// lumMod / lumOff / satMod / satOff / hueMod / hueOff
// → ST_Percentage: SIGNED and may exceed 100%
// (e.g. satMod200% to over-saturate, or
// satOff-10% to desaturate). Rejecting
// negatives wrongly aborted replay of the
// round-trip form Get emits for these
// (satOff val="-10000" → "satOff-10").
// Only the fixed-percentage family stays clamped 0..100.
bool fixedPct = name.ToLowerInvariant() is "shade" or "tint" or "alpha";View on GitHub (pinned to 1ced45e900)
Solutions
- Use one of the nine valid names exactly: lumMod, lumOff, shade, tint, satMod, satOff, hueMod, hueOff, alpha (case-insensitive).
- Check the spelling — 'lummode' vs 'lumMod', 'tintt' vs 'tint'.
- Map the desired effect to the closest OOXML transform (e.g. 'brightness' -> lumMod/lumOff).
Example fix
// before — unsupported name fill="red lummode50" // after — canonical OOXML name fill="red lumMod50"
Defensive patterns
Strategy: validation
Validate before calling
static readonly HashSet<string> ValidTransforms = new(StringComparer.OrdinalIgnoreCase)
{ "lumMod","lumOff","shade","tint","satMod","satOff","hueMod","hueOff","alpha" };
static bool IsValidTransformName(string token)
{
int i = 0; while (i < token.Length && char.IsLetter(token[i])) i++;
return i > 0 && ValidTransforms.Contains(token.Substring(0, i));
} Type guard
static bool IsValidColorTransform(string token)
{
int i = 0; while (i < token.Length && char.IsLetter(token[i])) i++;
if (i == 0 || i == token.Length) return false;
if (!ValidTransforms.Contains(token.Substring(0, i))) return false;
var rest = token[i] == '=' ? token.Substring(i + 1) : token.Substring(i);
return int.TryParse(rest, out _);
} Try / catch
try { DrawingColorBuilder.Build(color); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unknown color transform", StringComparison.Ordinal))
{ errors.Add(ex.Message); /* surface typo to user */ } Prevention
- Use the nine canonical OOXML transform names.
- Validate the transform name set before building color suffixes.
- Watch for casing/spelling drift from docs.
When it happens
Trigger: A color suffix token like 'lumMod50%' where the letter prefix isn't one of the nine known transforms — e.g. 'brightness50', 'mod50', 'lum50', a misspelled 'lummode'. The name is everything up to the first non-letter.
Common situations: User writes a color transform using a PowerPoint-UI name or a different library's vocabulary instead of the OOXML transform names; typo in a round-tripped value; copying a transform name from docs that uses a different casing/spelling.
Related errors
- Invalid color transform '{token}': raw value {raw} out of ra
- Invalid color transform '{token}': value must be an integer.
- Invalid color transform '{token}': raw value {raw} below 100
- Invalid color transform '{token}': percentage {raw} out of r
- invalid_input
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/bd418f7dd517da2a.
Report an issue: GitHub.