theonedev/onedev · error · ExplicitException
Unexpected operator: ${operator}
Error message
Unexpected operator: ${operator} What it means
When parsing a bare operator criterion (an operator with no value, e.g. 'owned by me'-style tokens) the visitor switches on the operator token and throws ExplicitException('Unexpected operator: X') for any operator not supported as a standalone criterion in project queries.
Source
Thrown at server-core/src/main/java/io/onedev/server/search/entity/project/ProjectQuery.java:137
switch (ctx.operator.getType()) {
case Roots:
return new RootsCriteria();
case Leafs:
return new LeafsCriteria();
case ForkRoots:
return new ForkRootsCriteria();
case OwnedByMe:
return new OwnedByMeCriteria();
case OwnedByNone:
return new NoOwnerCriteria();
case WithoutEnoughReplicas:
return new WithoutEnoughReplicasCriteria();
case HasOutdatedReplicas:
return new HasOutdatedReplicasCriteria();
case MissingStorage:
return new MissingStorageCriteria();
default:
throw new ExplicitException("Unexpected operator: " + ctx.operator.getText());
}
}
public Criteria<Project> visitOperatorValueCriteria(OperatorValueCriteriaContext ctx) {
var criterias = new ArrayList<Criteria<Project>>();
for (var quoted: ctx.criteriaValue.Quoted()) {
String value = getValue(quoted.getText());
if (ctx.operator.getType() == ChildrenOf)
criterias.add(new ChildrenOfCriteria(value));
else if (ctx.operator.getType() == ForksOf)
criterias.add(new ForksOfCriteria(value));
else
criterias.add(new OwnedByUserCriteria(getUser(value)));
}
return Criteria.orCriterias(criterias);
}
@OverrideView on GitHub (pinned to d44925c47c)
Solutions
- Use only operators supported for project queries without values (e.g. OwnedByMe, SubmittedByMe equivalents, ToBeDeleted).
- Move value-based operators into 'operator(value)' form handled by visitOperatorValueCriteria.
- Catch ExplicitException and display the message, guiding the user to valid operators.
- Check the switch in ProjectQuery.visitOperatorCriteria for the exact supported set.
Example fix
// before
ProjectQuery.parse("has builds"); // 'has' not a bare operator for projects
// after
ProjectQuery.parse("to be deleted"); // supported bare operator Defensive patterns
Strategy: validation
Validate before calling
// only these bare operators are valid for projects: check before parsing
Set<String> allowed = Set.of("owned by me", "to be deleted"); Type guard
null
Try / catch
try { q = ProjectQuery.parse(text); } catch (ExplicitException e) { show(e.getMessage()); } Prevention
- Use only project-supported bare operators
- Do not copy bare operators from issue/pull-request queries
- Offer operator autocompletion in query editors
- Catch ExplicitException for user-facing validation
When it happens
Trigger: A project query uses a bare operator token that exists in the grammar but is not handled in visitOperatorCriteria's switch (e.g. an operator valid for issues but not projects), hitting the default branch.
Common situations: Reusing issue/pull-request query syntax in project queries; typos in operator names; queries copied from documentation for a different entity type.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unexpected operator ${operator}
- Field not found: ${fieldName}
- Invalid number: ${value}
- Invalid decimal: ${value}
- Invalid reference number: <numberString>
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/29a83a8f27bb53a2.
Report an issue: GitHub.