quarkusio/quarkus · error · TemplateException
Not a binary operator:
Error message
Not a binary operator:
What it means
In IfSectionHelper, the internal BooleanRepresentation switch handles logical binary operators; if the stored operator code is not one of the known operators, evaluate() throws TemplateException("Not a binary operator: " + this). This signals an internal inconsistency: the parser produced an operator the evaluator does not recognize, or the helper state was corrupted.
Source
Thrown at independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java:492
return precedence;
}
boolean evaluate(Object op1, Object op2) {
switch (this) {
case EQ:
return equals(op1, op2);
case NE:
return !equals(op1, op2);
case GE:
case GT:
case LE:
case LT:
return compare(op1, op2);
case AND:
case OR:
return !isFalsy(op2);
default:
throw new TemplateException("Not a binary operator: " + this);
}
}
boolean equals(Object op1, Object op2) {
if (Objects.equals(op1, op2)) {
return true;
}
if (op1 != null && op2 != null && (op1 instanceof Number || op2 instanceof Number)) {
// Both operands are not null and at least one of them is a number
return getDecimal(op1).compareTo(getDecimal(op2)) == 0;
}
return false;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
boolean compare(Object op1, Object op2) {
if (op1 == null || op2 == null) {
throw new TemplateException("Unable to compare null operands [op1=" + op1 + ", op2=" + op2 + "]");View on GitHub (pinned to e1c734241f)
Solutions
- Verify the template's {#if} expression uses supported operators (&&, ||, comparison) and no stray characters.
- Upgrade/align Quarkus and Qute versions so parser and evaluator agree on operator codes.
- Report it as a bug if a plain supported expression triggers it — it indicates an internal parser/evaluator mismatch.
Example fix
// before
{#if a ??? b} // unsupported/misparsed operator
// after
{#if a ?: b} // use the supported elvis operator Defensive patterns
Strategy: try-catch
Validate before calling
// validate operator syntax ahead of time
if (!SUPPORTED_OPERATORS.contains(opToken)) {
throw new IllegalArgumentException("unsupported operator: " + opToken);
} Type guard
boolean isKnownBinaryOp(IfSectionHelper.BooleanRepresentation op) {
return op == AND || op == OR; // extend per known set
} Try / catch
try {
return condition.evaluate(ctx);
} catch (TemplateException ex) {
if (ex.getMessage().startsWith("Not a binary operator")) {
throw new IllegalArgumentException("Malformed {#if} expression — check template syntax/versions", ex);
}
throw ex;
} Prevention
- Keep parser and evaluator versions aligned (same Quarkus/Qute release)
- Use documented operators only (&&, ||, ?:, comparisons)
- Report occurrences on stock syntax as upstream bugs with the template snippet
When it happens
Trigger: Reaching the default branch of the operator switch during {#if} evaluation — an unrecognized/comparator operator leaked into the boolean-operator path, typically due to an internal bug, malformed custom operator registration, or version mismatch.
Common situations: Custom operator extensions or forks of Qute; template syntax accepted by one Qute version but not the evaluator of another after an upgrade; corrupted cached template state.
Related errors
- Not a short-circuiting operator:
- Invalid composite parameter found:
- Expression not found for param []:
- Unsupported param type:
- Invalid template link [${templateLink}] - Expeting a link th
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/69e5f8277ba425c1.
Report an issue: GitHub.