hibernate/hibernate-orm · error · SemanticException
Illegal operator for temporal type: {}
Error message
Illegal operator for temporal type: {} What it means
When both operands of a binary arithmetic expression are temporal (date/time/timestamp), the only defined operation is SUBTRACT, which produces a duration. Any other operator between two temporal values is ill-formed and rejected with a SemanticException naming the operator.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java:7286
inferrableTypeAccessStack.pop();
adjustmentScale = scale;
negativeAdjustment = negate;
}
default:
throw new SemanticException( "Illegal operator for a duration " + operator );
}
}
private Object transformDatetimeArithmetic(SqmBinaryArithmetic<?> expression) {
final var operator = expression.getOperator();
// the only kind of algebra we know how to
// do on dates/timestamps is subtract them,
// producing a duration - all other binary
// operator expressions with two dates or
// timestamps are ill-formed
if ( operator != SUBTRACT ) {
throw new SemanticException( "Illegal operator for temporal type: " + operator );
}
// a difference between two dates or two
// timestamps is a leaf duration, so we
// must apply the scale, and the 'by unit'
// ts1 - ts2
final var lhs = SqmExpressionHelper.getActualExpression( expression.getLeftHandOperand() );
final var rhs = SqmExpressionHelper.getActualExpression( expression.getRightHandOperand() );
final var fromClauseIndex = fromClauseIndexStack.getCurrent();
inferrableTypeAccessStack.push( () -> determineValueMapping( rhs, fromClauseIndex ) );
final var left = getActualExpression( cleanly( () -> toSqlExpression( lhs.accept( this ) ) ) );
inferrableTypeAccessStack.pop();
inferrableTypeAccessStack.push( () -> determineValueMapping( lhs, fromClauseIndex ) );
final var right = getActualExpression( cleanly( () -> toSqlExpression( rhs.accept( this ) ) ) );
inferrableTypeAccessStack.pop();
View on GitHub (pinned to fad1729dce)
Solutions
- Use subtraction for span calculations: 'date1 - date2'
- Shift timestamps by durations instead: 'ts + 1 day'
- Use dialect functions (add_months, dateadd...) via native SQL or function templates for other date combinations
Example fix
// before select o.dueDate + o.createdOn from Ord o // after select o.dueDate - o.createdOn from Ord o
Defensive patterns
Strategy: try-catch
Validate before calling
if (isTemporalPath(left) && isTemporalPath(right) && operator != '-') {
throw new IllegalArgumentException("Only date1 - date2 is defined between two temporal values");
} Try / catch
try {
return session.createQuery(hql).getResultList();
} catch (org.hibernate.query.SemanticException e) {
log.error("Temporal operator rejected: {}", hql, e);
throw e;
} Prevention
- Use subtraction for spans and 'ts + duration' for shifts
- Use dialect date functions for anything else
- Type-check generated arithmetic against mapped attribute Java types
When it happens
Trigger: HQL like 'date1 + date2', 'ts1 * ts2', or predicates where two mapped temporal attributes are combined with an operator other than minus.
Common situations: Naive date math ported from scripting languages; generated queries that apply the same arithmetic template to all numeric-looking columns; refactors that swap an operand from a number to a date column without changing the operator.
Related errors
- Scalar multiplication of temporal value
- Illegal operator for a duration {}
- field type not supported on Derby: " + unit
- field type not supported on Derby: " + unit
- Function %s() requires exactly 3 arguments when invoked with
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/8a92761f78e8ad23.
Report an issue: GitHub.