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);
					}
					
					@Override

View on GitHub (pinned to d44925c47c)

Solutions

  1. Use only operators supported for project queries without values (e.g. OwnedByMe, SubmittedByMe equivalents, ToBeDeleted).
  2. Move value-based operators into 'operator(value)' form handled by visitOperatorValueCriteria.
  3. Catch ExplicitException and display the message, guiding the user to valid operators.
  4. 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

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/29a83a8f27bb53a2. Report an issue: GitHub.