hibernate/hibernate-orm · error · SemanticException
Operand of " + op.getOperatorSqlText() + " is of type '" + r
Error message
Operand of " + op.getOperatorSqlText() + " is of type '" + rightNodeType.getTypeName() + "' which is not a temporal amount (it is not an instance of 'java.time.TemporalAmount')
What it means
When the left operand of + or - is a java.time.TemporalAmount (Duration/Period), HQL only permits another TemporalAmount on the right: durations combine with durations. Any other right-hand type (number, string, date) fails this SemanticException during query parsing.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java:540
break;
default:
if ( !Number.class.isAssignableFrom( rightJavaType ) ) {
throw new SemanticException(
"Operand of " + op.getOperatorSqlText() + " is of type '" + rightNodeType.getTypeName() +
"' which is not a numeric type (it is not an instance of 'java.lang.Number')"
);
}
break;
}
}
else if ( TemporalAmount.class.isAssignableFrom( leftJavaType ) ) {
// left operand is a duration
switch (op) {
case ADD:
case SUBTRACT:
// we can add/subtract durations
if ( !TemporalAmount.class.isAssignableFrom( rightJavaType ) ) {
throw new SemanticException(
"Operand of " + op.getOperatorSqlText() + " is of type '" + rightNodeType.getTypeName() +
"' which is not a temporal amount (it is not an instance of 'java.time.TemporalAmount')"
);
}
break;
default:
throw new SemanticException(
"Operand of " + op.getOperatorSqlText() + " is of type '" + leftNodeType.getTypeName() +
"' which is not a numeric type (it is not an instance of 'java.lang.Number')"
);
}
}
else if ( Temporal.class.isAssignableFrom( leftJavaType )
|| java.util.Date.class.isAssignableFrom( leftJavaType ) ) {
// left operand is a date, time, or datetime
switch (op) {
case ADD:
// we can add a duration to date, time, or datetimeView on GitHub (pinned to fad1729dce)
Solutions
- Combine only duration with duration: `e.warranty - 30 day`
- To scale a duration, multiply with the NUMBER on the left: `2 * e.duration`
- For date/datetime arithmetic keep the date on the left: `e.dueDate + 3 day`
- Use proper HQL duration literals (`3 day`, `2 hour`) instead of plain integers or strings
Example fix
// before select e.warranty - 30 from Contract e // after select e.warranty - 30 day from Contract e
Defensive patterns
Strategy: try-catch
Validate before calling
// Before combining duration expressions, confirm both are TemporalAmount
static boolean isDuration(Attribute<?, ?> a) {
return java.time.temporal.TemporalAmount.class.isAssignableFrom(a.getJavaType());
} Type guard
static boolean durationMathOk(Class<?> left, Class<?> right, String op) {
if (java.time.temporal.TemporalAmount.class.isAssignableFrom(left)) {
return ("+".equals(op) || "-".equals(op))
&& java.time.temporal.TemporalAmount.class.isAssignableFrom(right);
}
return true; // other cases handled by their own guards
} Try / catch
try {
return em.createQuery(hql, Duration.class).getResultList();
} catch (org.hibernate.query.SemanticException e) {
throw new QueryBuildException("Duration +/- requires a duration operand: " + hql, e);
} Prevention
- Combine durations only with durations (`e.warranty - 30 day`, not `- 30`)
- Scale durations by putting the number on the LEFT of '*'
- Prefer typed CriteriaBuilder expressions over string HQL for duration math
When it happens
Trigger: `e.duration - 1` (subtracting a plain number); `e.warranty + current_date`; `(e.endDate - e.startDate) + e.name`; `e.duration + 'PT2H'` (string literal instead of a duration literal).
Common situations: Trying to shorten/lengthen a duration with an integer (`duration - 30` instead of `duration - 30 day`); mixing up the rule that dates plus durations work but durations plus numbers do not; porting native SQL INTERVAL expressions from PostgreSQL/Oracle to HQL.
Related errors
- Operand of " + op.getOperatorSqlText() + " is of type '" + r
- Operand of " + op.getOperatorSqlText() + " is of type '" + r
- Operand of " + op.getOperatorSqlText() + " is of type '" + l
- Operand of " + op.getOperatorSqlText() + " is of type '" + l
- Operand of 'by' is of type '" + nodeType.getTypeName() + "'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/c8ad2b68a6dc8dcb.
Report an issue: GitHub.