halo-dev/halo · error · IllegalArgumentException
Unsupported operator: {}
Error message
Unsupported operator: {} What it means
Thrown by FieldSelectorConverter.convert when the SelectorCriteria operator is not one of Equals, NotEquals, or IN (the only operators the field-selector path handles). The Operator enum also defines Exist and NotExist, which are valid for label selectors but have no field-selector query, so a field selector using bare-key existence (`fieldKey`) or negated existence (`!fieldKey`) hits the default branch and throws.
Source
Thrown at api/src/main/java/run/halo/app/extension/router/selector/FieldSelectorConverter.java:32
public Condition convert(SelectorCriteria criteria) {
var key = criteria.key();
// compatible with old field selector
if ("name".equals(key)) {
key = "metadata.name";
}
switch (criteria.operator()) {
case Equals -> {
return Queries.equal(key, getSingleValue(criteria));
}
case NotEquals -> {
return Queries.notEqual(key, getSingleValue(criteria));
}
// compatible with old field selector
case IN -> {
Set<String> valueArr = defaultIfNull(criteria.values(), Set.of());
return Queries.in(key, valueArr);
}
default -> throw new IllegalArgumentException("Unsupported operator: " + criteria.operator());
}
}
String getSingleValue(SelectorCriteria criteria) {
if (CollectionUtils.isEmpty(criteria.values())) {
throw new IllegalArgumentException("No value present for label key: " + criteria.key());
}
return criteria.values().iterator().next();
}
}
View on GitHub (pinned to d2f5165f9c)
Solutions
- For field selectors, use only value operators: key=value, key!=value, or key in (a,b). Move existence checks to labelSelector where Exist/NotExist are supported.
- If you construct SelectorCriteria programmatically, restrict the operator to Equals/NotEquals/IN for field selectors.
- Upgrade both api and application modules together so a new operator is handled on both converter paths.
Example fix
// before GET /apis?fieldSelector=name // after GET /apis?labelSelector=app%3Dhalo // use label existence, or GET /apis?fieldSelector=name=in%20(a,b)
Defensive patterns
Strategy: validation
Validate before calling
Set<Operator> supported = EnumSet.of(Operator.Equals, Operator.NotEquals, Operator.IN);
if (!supported.contains(criteria.operator())) {
throw new IllegalArgumentException(
"Field selector supports only =, !=, and in; got " + criteria.operator());
} Type guard
boolean fieldSupported = switch (criteria.operator()) {
case Equals, NotEquals, IN -> true;
default -> false;
}; Try / catch
try {
Condition cond = new FieldSelectorConverter().convert(criteria);
} catch (IllegalArgumentException e) {
// re-educate the caller: field selectors accept only value operators
} Prevention
- Use labelSelector (not fieldSelector) for bare-key existence checks.
- Document that fieldSelector supports only =, !=, and in().
- Keep api and application versions aligned so new operators get cases.
When it happens
Trigger: A `?fieldSelector=name` (Exist) or `?fieldSelector=!status` (NotExist) query reaches FieldSelectorConverter; or a future Operator enum constant is added without a case here.
Common situations: A client reuses label-selector syntax (bare key for existence) on a fieldSelector query; an SDK builds a SelectorCriteria with Exist/NotExist against field keys; upgrading Halo adds an operator not yet mapped.
Related errors
- No value present for label key: {}
- Unsupported operator: {}
- No value present for label key: {}
- Unexpected APIVersion string: {}
- No such thumbnail size: {}
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/40ee3e68fde5b54c.
Report an issue: GitHub.