hibernate/hibernate-orm · error · SemanticException
Operand of " + op.getOperatorSqlText() + " is of type '" + l
Error message
Operand of " + op.getOperatorSqlText() + " is of type '" + leftNodeType.getTypeName() + "' which is not a numeric type (it is not an instance of 'java.lang.Number')
What it means
When the left operand is a TemporalAmount (duration) but the operator is anything other than + or - (i.e. *, /, %), assertOperable rejects the expression and the message names the LEFT operand's type as 'not a numeric type'. Hibernate only defines scaling for durations via multiplication with the number on the LEFT, so `duration * n` is illegal while `n * duration` is fine.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java:547
}
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 datetime
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;View on GitHub (pinned to fad1729dce)
Solutions
- Swap the operands so the number comes first: `2 * e.duration`
- Rewrite `(e.endDate - e.startDate) * 1.5` as `1.5 * (e.endDate - e.startDate)`
- If you need the duration as a number first, convert with `by`: `(e.endDate - e.startDate) by day * 1.5` — wait, that yields a number; simply scale the numeric result
Example fix
// before select (e.endDate - e.startDate) * 2 from Booking e // after select 2 * (e.endDate - e.startDate) from Booking e
Defensive patterns
Strategy: validation
Validate before calling
// When scaling durations programmatically, always order number first
static String scale(String durationExpr, String factor) {
// '2 * duration' is valid; 'duration * 2' is not
return factor + " * (" + durationExpr + ")";
} Try / catch
try {
return session.createQuery(hql).list();
} catch (org.hibernate.query.SemanticException e) {
if (e.getMessage().contains("not a numeric type")) {
throw new QueryBuildException("Move the numeric factor to the LEFT of '*': " + hql, e);
}
throw e;
} Prevention
- Canonical rule: multiplication with a duration always reads `number * duration`
- Review any query copied from PostgreSQL that multiplies intervals both ways
- Unit-test duration-scaling queries against H2/PostgreSQL in CI
When it happens
Trigger: `e.duration * 2`; `(e.endDate - e.startDate) * 1.5`; `e.duration / 2`; `e.period % 7` — any *, /, or % whose left side is a Duration/Period attribute or duration expression.
Common situations: Scaling a computed duration such as `(end - start) * 2` — very common in reporting queries; PostgreSQL habit where `interval * int` and `int * interval` both work; developers confused because the error points at the left operand's type.
Related errors
- Operand of " + op.getOperatorSqlText() + " is of type '" + r
- Operand of 'by' is of type '" + nodeType.getTypeName() + "'
- Operand of " + op.getOperatorSqlText() + " is of type '" + r
- Operand of " + op.getOperatorSqlText() + " is of type '" + r
- Operand of " + op.getOperatorSqlText() + " is of type '" + r
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/0035e694490ba66d.
Report an issue: GitHub.