iOfficeAI/OfficeCLI · error · ArgumentException
Unsupported criteria operator: '{op}'. Valid: equals, notEqu
Error message
Unsupported criteria operator: '{op}'. Valid: equals, notEquals, contains, doesNotContain, beginsWith, endsWith, gt, gte, lt, lte, between, notBetween, top, topPercent, bottom, bottomPercent, blanks, nonBlanks, values, dynamic. What it means
Thrown by AddAutoFilter's default switch case when the operator in a criteriaN.OP=VAL property key is not one of the recognized names. The operator is extracted by the regex ^criteria(\d+).([A-Za-z]+)$ and lower-cased, then dispatched; an unrecognized name means the criteria cannot be mapped to an Excel filter element. The message lists every valid operator so the caller can self-correct.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs:940
.ToList();
var filters = filterColumn.Filters ?? (filterColumn.Filters = new Filters());
foreach (var v in vals)
filters.AppendChild(new Filter { Val = v });
handledDedicated = true;
break;
}
case "dynamic":
{
var dyn = new DynamicFilter
{
Type = new EnumValue<DynamicFilterValues>(new DynamicFilterValues(rawVal))
};
filterColumn.DynamicFilter = dyn;
handledDedicated = true;
break;
}
default:
throw new ArgumentException(
$"Unsupported criteria operator: '{op}'. Valid: equals, notEquals, contains, doesNotContain, beginsWith, endsWith, gt, gte, lt, lte, between, notBetween, top, topPercent, bottom, bottomPercent, blanks, nonBlanks, values, dynamic.");
}
}
if (customEntries.Count > 0 && !handledDedicated)
{
var cf = new CustomFilters();
if (customFilterAnd)
cf.And = true;
foreach (var (fop, val) in customEntries)
cf.AppendChild(new CustomFilter
{
Operator = fop,
Val = val
});
filterColumn.CustomFilters = cf;
}
autoFilter.AppendChild(filterColumn);
}View on GitHub (pinned to 1ced45e900)
Solutions
- Use one of the listed operators exactly: equals, notEquals, contains, doesNotContain, beginsWith, endsWith, gt, gte, lt, lte, between, notBetween, top, topPercent, bottom, bottomPercent, blanks, nonBlanks, values, dynamic.
- Note the operator is matched case-insensitively, but must match a whitelist entry verbatim otherwise.
- If you need a range filter, use between with a 'lo,hi' value.
Example fix
// before --prop criteria0.contain=foo // after --prop criteria0.contains=foo
Defensive patterns
Strategy: validation
Validate before calling
static readonly HashSet<string> ValidFilterOps = new(StringComparer.OrdinalIgnoreCase)
{
"equals","notEquals","contains","doesNotContain","beginsWith","endsWith",
"gt","gte","lt","lte","between","notBetween",
"top","topPercent","bottom","bottomPercent",
"blanks","nonBlanks","values","dynamic"
};
static bool TryValidateCriteriaOp(string op, out string error)
{
if (ValidFilterOps.Contains(op)) { error = null; return true; }
error = $"Unsupported criteria operator: '{op}'. Valid: " + string.Join(", ", ValidFilterOps) + ".";
return false;
} Type guard
static bool IsValidFilterOp(string op) => ValidFilterOps.Contains(op);
Try / catch
try { handler.Add(path, "autofilter", null, props); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unsupported criteria operator"))
{ /* surface the whitelist to the caller; likely a typo in criteriaN.OP */ } Prevention
- Offer the operator list as an enum or autocomplete set in any UI that builds criteria keys.
- Strip stray characters from operator names before constructing the criteriaN.OP key.
- Log the failing operator so typos are obvious in error reports.
When it happens
Trigger: A typo in the operator segment of the key: criteria0.contain=x (missing 's'), criteria0.greaterthan=5 (use 'gt'), criteria0.between2=1,2, or any other key whose OP segment is alphabetic but not in the whitelist.
Common situations: Misremembering operator names, mixing camelCase expectations with the actual lowercase names, or relying on an operator the handler never implemented.
Related errors
- Property 'sqref' (or 'range'/'ref') is required for validati
- AutoFilter requires 'range' property (e.g. range=A1:F100)
- Invalid 'range' value: '{afRange}'. Expected a cell range li
- criteria{colId}.{op} requires 'lo,hi', got: '{rawVal}'
- criteria{colId}.{op} requires a numeric value, got: '{rawVal
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/2009539a7824c40c.
Report an issue: GitHub.