{"record":{"id":"f42b2e79d2f229b1","repo":"iOfficeAI/OfficeCLI","slug":"invalid-color-transform-token-raw-value-raw","errorCode":null,"errorMessage":"Invalid color transform '{token}': raw value {raw} out of range {minRaw}-{maxRaw}.","messagePattern":"Invalid color transform '(.+?)': raw value (.+?) out of range (.+?)-(.+?)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"warning","filePath":"src/officecli/Core/DrawingColorBuilder.cs","lineNumber":141,"sourceCode":"            //                           negatives forbidden.\n            //   lumMod / lumOff / satMod / satOff / hueMod / hueOff\n            //                         → ST_Percentage: SIGNED and may exceed 100%\n            //                           (e.g. satMod200% to over-saturate, or\n            //                           satOff-10% to desaturate). Rejecting\n            //                           negatives wrongly aborted replay of the\n            //                           round-trip form Get emits for these\n            //                           (satOff val=\"-10000\" → \"satOff-10\").\n            // Only the fixed-percentage family stays clamped 0..100.\n            bool fixedPct = name.ToLowerInvariant() is \"shade\" or \"tint\" or \"alpha\";\n            int maxPct = fixedPct ? 100 : 1000;       // 1000% headroom for ST_Percentage\n            int minPct = fixedPct ? 0 : -1000;        // signed for the Mod/Off family\n            int maxRaw = fixedPct ? 100000 : 1000000;\n            int minRaw = fixedPct ? 0 : -1000000;\n            int pct;\n            if (eqForm)\n            {\n                if (raw < minRaw || raw > maxRaw)\n                    throw new ArgumentException(\n                        $\"Invalid color transform '{token}': raw value {raw} out of range {minRaw}-{maxRaw}.\");\n                // OOXML raw units are 1/1000 of a percent. Integer division\n                // truncates values whose magnitude is 1..999 to 0 (lumMod=75 raw\n                // → 0 instead of 7.5%). Reject sub-1000 magnitudes so callers\n                // can't silently get a no-op; the percentage form covers that range.\n                if (raw != 0 && Math.Abs(raw) < 1000)\n                    throw new ArgumentException(\n                        $\"Invalid color transform '{token}': raw value {raw} below 1000 truncates to 0%; use percentage form '{name}{raw / 1000}' or raw magnitude >= 1000.\");\n                pct = raw / 1000;\n            }\n            else\n            {\n                if (raw < minPct || raw > maxPct)\n                    throw new ArgumentException(\n                        $\"Invalid color transform '{token}': percentage {raw} out of range {minPct}-{maxPct}.\");\n                pct = raw;\n            }\n            // Canonicalize: lumMod → lumMod (lowercase first letter? OOXML uses","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/DrawingColorBuilder.cs#L123-L159","documentation":"In eqForm (token had '='), the parsed raw integer fell outside the OOXML range for that transform family. For fixed-percentage transforms (shade/tint/alpha) the raw range is 0..100000; for the signed Mod/Off family (lumMod/lumOff/satMod/satOff/hueMod/hueOff) it is -1000000..1000000. The bounds reflect the OOXML ST_PositiveFixedPercentage vs ST_Percentage schema types.","triggerScenarios":"An eqForm value beyond the schema ceiling/floor: 'shade=200000' (fixed-pct max 100000), 'alpha=150000', 'lumMod=5000000', or a negative fixed-pct like 'shade=-10000'. minRaw/maxRaw in the message state the exact allowed range.","commonSituations":"Confusing raw OOXML units (1/1000 of a percent) with plain percentages and entering a too-large number; trying to over-apply a fixed-percentage transform past 100%; using a negative where the schema forbids it.","solutions":["Use the percentage form instead of raw eqForm for human-scale values: 'shade85' rather than 'shade=85000'.","Keep fixed-percentage transforms (shade/tint/alpha) within 0..100 (raw 0..100000).","Keep Mod/Off transforms within -1000..1000 percent (raw -1000000..1000000)."],"exampleFix":"// before — raw eqForm out of range\nfill=\"red shade=200000\"\n\n// after — percentage form, clamped to valid range\nfill=\"red shade100\"","handlingStrategy":"validation","validationCode":"static (int min, int max) RawRange(string name)\n{\n    bool fixedPct = name.ToLowerInvariant() is \"shade\" or \"tint\" or \"alpha\";\n    return fixedPct ? (0, 100000) : (-1000000, 1000000);\n}\n// Validate before building: ensure raw eqForm value lies within RawRange(name).","typeGuard":null,"tryCatchPattern":"try { DrawingColorBuilder.Build(color); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"out of range\", StringComparison.Ordinal))\n{ errors.Add(ex.Message); }","preventionTips":["Prefer the percentage form over raw eqForm for human-scale values.","Remember raw OOXML = 1/1000 percent, so large raw numbers are normal.","Keep fixed-percentage transforms (shade/tint/alpha) within 0..100%."],"tags":["color","transform","validation","range","ooxml","user-input"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}