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

  1. Switch to percentage form: 'lumMod75' for 75% instead of 'lumMod=75'.
  2. 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

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


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/32fd06a7713e3641. Report an issue: GitHub.