theonedev/onedev · error · ExplicitException
Unexpected criteria: ${operator}
Error message
Unexpected criteria: ${operator} What it means
In visitOperatorValueCriteria, PackQuery maps operator-value criteria like 'published by <user>', 'published by build <n>', 'published by project <x>' to concrete Criteria classes. If the operator token matches none of the known patterns, it throws ExplicitException("Unexpected criteria: <operator>").
Source
Thrown at server-core/src/main/java/io/onedev/server/search/entity/pack/PackQuery.java:123
return new PublishedByMeCriteria();
default:
throw new ExplicitException("Unexpected operator: " + ctx.operator.getText());
}
}
@Override
public Criteria<Pack> visitOperatorValueCriteria(PackQueryParser.OperatorValueCriteriaContext ctx) {
var criterias = new ArrayList<Criteria<Pack>>();
for (var quoted: ctx.criteriaValue.Quoted()) {
String value = getValue(quoted.getText());
if (ctx.PublishedByUser() != null)
criterias.add(new PublishedByUserCriteria(getUser(value)));
else if (ctx.PublishedByBuild() != null)
criterias.add(new PublishedViaBuildCriteria(project, value));
else if (ctx.PublishedByProject() != null)
criterias.add(new PublishedViaProjectCriteria(value));
else
throw new ExplicitException("Unexpected criteria: " + ctx.operator.getText());
}
return Criteria.orCriterias(criterias);
}
@Override
public Criteria<Pack> visitFieldOperatorValueCriteria(FieldOperatorValueCriteriaContext ctx) {
String fieldName = getValue(ctx.criteriaField.getText());
int operator = ctx.operator.getType();
checkField(project, fieldName, operator);
var criterias = new ArrayList<Criteria<Pack>>();
for (var quoted: ctx.criteriaValue.Quoted()) {
String value = getValue(quoted.getText());
switch (operator) {
case IsUntil:
case IsSince:
if (fieldName.equals(NAME_PUBLISH_DATE))
criterias.add(new PublishDateCriteria(value, operator));View on GitHub (pinned to d44925c47c)
Solutions
- Use one of the supported forms: 'published by <user>', 'published by build <n>', 'published by project <name>'
- Validate the query in the UI editor before saving/calling the API
- Catch ExplicitException to report the offending operator to the user
Example fix
// before "published by user john" // unsupported form // after "published by john"
Defensive patterns
Strategy: validation
Validate before calling
const valid = /^published by (build \d+|project \S+|\S+)$/i; q.split(/\b(?:and|or)\b/i).forEach(c => { if (/published by/i.test(c) && !valid.test(c.trim())) throw new Error('bad operator-value criterion: ' + c.trim()); }); Type guard
null
Try / catch
try { PackQuery.parse(project, q); } catch (ExplicitException e) { if (e.getMessage().startsWith('Unexpected criteria')) showError(e.getMessage()); else throw e; } Prevention
- Use exact supported forms: 'published by <user>', 'published by build <n>', 'published by project <name>'
- Avoid free-form operator naming
- Lint saved queries periodically
When it happens
Trigger: A pack query operator-value criterion whose operator is not PublishedByUser, PublishedByBuild, or PublishedByProject — e.g. typo'd or unsupported operator with a value attached, or query text from a different grammar version.
Common situations: Typos like 'published by user john' vs 'published by john'; reusing issue/build query operators on pack queries; version drift between saved queries and current parser.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
Related errors
- Criteria '${operator}' is not supported here
- Unexpected operator: ${operator}
- Cannot order by field: ${fieldName}
- Field not found: ${fieldName}
- Invalid number: ${value}
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/49f6f5e375958a3d.
Report an issue: GitHub.