iOfficeAI/OfficeCLI · warning · ArgumentException
Invalid color transform '{token}': raw value {raw} below 100
Error message
Invalid color transform '{token}': raw value {raw} below 1000 truncates to 0%; use percentage form '{name}{raw / 1000}' or raw magnitude >= 1000. What it means
In eqForm, the raw integer had magnitude 1..999. Because OOXML raw units are 1/1000 of a percent, integer division (raw/1000) truncates such values to 0 — a silent no-op. The parser rejects these and points the user to the percentage form (e.g. 'lumMod75'), which covers that magnitude correctly.
Source
Thrown at src/officecli/Core/DrawingColorBuilder.cs:148
// (satOff val="-10000" → "satOff-10").
// Only the fixed-percentage family stays clamped 0..100.
bool fixedPct = name.ToLowerInvariant() is "shade" or "tint" or "alpha";
int maxPct = fixedPct ? 100 : 1000; // 1000% headroom for ST_Percentage
int minPct = fixedPct ? 0 : -1000; // signed for the Mod/Off family
int maxRaw = fixedPct ? 100000 : 1000000;
int minRaw = fixedPct ? 0 : -1000000;
int pct;
if (eqForm)
{
if (raw < minRaw || raw > maxRaw)
throw new ArgumentException(
$"Invalid color transform '{token}': raw value {raw} out of range {minRaw}-{maxRaw}.");
// OOXML raw units are 1/1000 of a percent. Integer division
// truncates values whose magnitude is 1..999 to 0 (lumMod=75 raw
// → 0 instead of 7.5%). Reject sub-1000 magnitudes so callers
// can't silently get a no-op; the percentage form covers that range.
if (raw != 0 && Math.Abs(raw) < 1000)
throw new ArgumentException(
$"Invalid color transform '{token}': raw value {raw} below 1000 truncates to 0%; use percentage form '{name}{raw / 1000}' or raw magnitude >= 1000.");
pct = raw / 1000;
}
else
{
if (raw < minPct || raw > maxPct)
throw new ArgumentException(
$"Invalid color transform '{token}': percentage {raw} out of range {minPct}-{maxPct}.");
pct = raw;
}
// Canonicalize: lumMod → lumMod (lowercase first letter? OOXML uses
// camelCase: lumMod, lumOff, satMod, satOff, hueMod, hueOff,
// shade, tint). KnownTransforms matches case-insensitively; we
// re-emit the canonical form here.
var canonical = name.ToLowerInvariant() switch
{
"lummod" => "lumMod",
"lumoff" => "lumOff",View on GitHub (pinned to 1ced45e900)
Solutions
- Switch to percentage form: 'lumMod75' for 75% instead of 'lumMod=75'.
- If raw OOXML is genuinely intended, use magnitude >= 1000 (e.g. 'lumMod=75000' for 75%).
Example fix
// before — small raw value silently truncates to 0% fill="red lumMod=75" // after — percentage form (75%) fill="red lumMod75"
Defensive patterns
Strategy: validation
Validate before calling
// For eqForm, require raw magnitude 0 or >= 1000
static bool RawTruncatesToZero(int raw) => raw != 0 && Math.Abs(raw) < 1000;
// If RawTruncatesToZero(raw), suggest percentage form "{name}{raw/1000}". Try / catch
try { DrawingColorBuilder.Build(color); }
catch (ArgumentException ex) when (ex.Message.Contains("truncates to 0%", StringComparison.Ordinal))
{ errors.Add(ex.Message); } Prevention
- Don't put small raw values in eqForm — they silently become 0%.
- Use percentage form for values under 100%.
- Reserve eqForm for true OOXML raw magnitudes (>= 1000).
When it happens
Trigger: A small raw eqForm value like 'lumMod=75' (intending 7.5% but meaning 0.075%), 'shade=500', or 'tint=999'. raw != 0 and Math.Abs(raw) < 1000 trips the guard.
Common situations: User thinks the eqForm number is a percentage and writes 'lumMod=75' meaning 75%, when 75 raw = 0.075% (and truncates to 0). The message suggests the percentage equivalent '{name}{raw/1000}'.
Related errors
- Unknown color transform '{name}'. Valid: lumMod, lumOff, sha
- Invalid color transform '{token}': value must be an integer.
- Invalid color transform '{token}': raw value {raw} out of ra
- Invalid color transform '{token}': percentage {raw} out of r
- mermaid syntax error: {msg} (fix the mermaid source, or use
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/32fd06a7713e3641.
Report an issue: GitHub.