iOfficeAI/OfficeCLI · error · System.ArgumentException

Unknown CF type '{cfTypeProp}'. Valid: databar, iconset, col

Error message

Unknown CF type '{cfTypeProp}'. Valid: databar, iconset, colorscale, formula, cellIs, top10, topPercent, bottom, bottomPercent, aboveAverage, belowAverage, uniqueValues, duplicateValues, containsText, notContains, beginsWith, endsWith, containsBlanks, notContainsBlanks, containsErrors, notContainsErrors, dateOccurring.

What it means

Thrown by AddDataBar (the conditionalformatting alias) when a type or rule property is supplied but does not match any known CF type and is not databar. This mirrors the AddCf allowlist (CONSISTENCY cf-type-allowlist) so both --type cf and --type conditionalformatting reject the same unknowns. databar is the documented default for this alias, so it is allowed explicitly; everything else unrecognized throws.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cf.cs:116

            if (cfTypeLower is "topn" or "top10" or "top") return Add(parentPath, "topn", position, properties);
            if (cfTypeLower is "toppercent") return AddTopRouted(parentPath, position, properties, percent: true, bottom: false);
            if (cfTypeLower is "bottom") return AddTopRouted(parentPath, position, properties, percent: false, bottom: true);
            if (cfTypeLower is "bottompercent") return AddTopRouted(parentPath, position, properties, percent: true, bottom: true);
            if (cfTypeLower is "aboveaverage") return Add(parentPath, "aboveaverage", position, properties);
            if (cfTypeLower is "uniquevalues") return Add(parentPath, "uniquevalues", position, properties);
            if (cfTypeLower is "duplicatevalues") return Add(parentPath, "duplicatevalues", position, properties);
            if (cfTypeLower is "containstext") return Add(parentPath, "containstext", position, properties);
            if (cfTypeLower is "dateoccurring" or "timeperiod") return Add(parentPath, "dateoccurring", position, properties);
            if (cfTypeLower is "belowaverage" or "containsblanks" or "notcontainsblanks" or "containserrors" or "notcontainserrors" or "contains" or "notcontains" or "beginswith" or "endswith")
                return Add(parentPath, "cfextended", position, properties);
            // R10: Reject unknown CF types instead of silently falling through to
            // dataBar. The `cf` alias (AddCf) already throws on unknowns; mirror
            // the behavior here so both `--type cf` and `--type conditionalformatting`
            // share the same allowlist (CONSISTENCY(cf-type-allowlist)). `databar`
            // is the documented default for this alias, so allow it explicitly.
            if (cfTypeLower is not "databar")
            {
                throw new ArgumentException(
                    $"Unknown CF type '{cfTypeProp}'. Valid: databar, iconset, colorscale, formula, cellIs, "
                    + "top10, topPercent, bottom, bottomPercent, aboveAverage, belowAverage, "
                    + "uniqueValues, duplicateValues, containsText, notContains, beginsWith, endsWith, "
                    + "containsBlanks, notContainsBlanks, containsErrors, notContainsErrors, dateOccurring.");
            }
        }
        var cfSegments = parentPath.TrimStart('/').Split('/', 2);
        var cfSheetName = cfSegments[0];
        var cfWorksheet = FindWorksheet(cfSheetName)
            ?? throw new ArgumentException($"Sheet not found: {cfSheetName}");

        // R22-2: a path-tail range (/Sheet1/A1:A3) is the sqref fallback before
        // the hardcoded "A1:A10" — previously csSegments[1] was silently ignored.
        var cfPathRange = cfSegments.Length > 1 && !string.IsNullOrEmpty(cfSegments[1]) ? cfSegments[1] : "A1:A10";
        var sqref = ValidateSqref(properties.GetValueOrDefault("sqref") ?? properties.GetValueOrDefault("range") ?? properties.GetValueOrDefault("ref", cfPathRange), "ref");
        var minVal = properties.ContainsKey("min") ? properties["min"] : (string?)null;
        var maxVal = properties.ContainsKey("max") ? properties["max"] : (string?)null;
        // The schema documents min/max as "numeric or 'auto'". 'auto' is the

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Correct the type/rule to a value from the allowlist in the message.
  2. Omit the type property to get the default data bar for this alias.
  3. Use the cf alias (type=cf) if you prefer its default-dispatch behavior.

Example fix

// before
props["type"] = "coloscale"; // typo
handler.Add("/Sheet1", "conditionalformatting", null, props);

// after
props["type"] = "colorscale";
handler.Add("/Sheet1", "conditionalformatting", null, props);
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<string> CfTypes = new(StringComparer.OrdinalIgnoreCase)
{ "databar","iconset","colorscale","formula","expression","cellis","topn","top10","top","toppercent","bottom","bottompercent","aboveaverage","belowaverage","uniquevalues","duplicatevalues","containstext","dateoccurring","timeperiod","containsblanks","notcontainsblanks","containserrors","notcontainserrors","contains","notcontains","beginswith","endswith" };
var t = props.GetValueOrDefault("type") ?? props.GetValueOrDefault("rule");
if (t != null && !CfTypes.Contains(t))
    throw new ArgumentOutOfRangeException("type", $"Unknown CF type: {t}");
handler.Add("/Sheet1", "conditionalformatting", null, props);

Type guard

static bool IsKnownCfType(string? t) => t == null || CfTypes.Contains(t);

Prevention

When it happens

Trigger: Add type=conditionalformatting with properties["type"]="badtype" or rule="colorscaleX". Any value not in the shared allowlist and not databar. The guard only runs when a type/rule property is present; omitting it yields a plain data bar. Case-insensitive comparison via ToLowerInvariant.

Common situations: Typo in the type name. Using a type valid for the cf alias but spelled differently. Passing a type meant for a different element. Copying a value from older docs whose allowlist differed.

Related errors


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