hibernate/hibernate-orm · error · SemanticException
Scalar multiplication of temporal value
Error message
Scalar multiplication of temporal value
What it means
In binary arithmetic translation, the left operand resolved to a temporal type and the right to a duration, but a scale was already pending (adjustmentScale non-null) or a negation was queued. SQL cannot distribute a multiplication or division over a date/timestamp - only durations may be scaled - so the SemanticException rejects it.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java:7089
// Need to infer the operand types here first to decide how to transform the expression
final var fromClauseIndex = fromClauseIndexStack.getCurrent();
inferrableTypeAccessStack.push( () -> determineValueMapping( rightOperand, fromClauseIndex ) );
final var leftOperandType = determineValueMapping( leftOperand );
inferrableTypeAccessStack.pop();
inferrableTypeAccessStack.push( () -> determineValueMapping( leftOperand, fromClauseIndex ) );
final var rightOperandType = determineValueMapping( rightOperand );
inferrableTypeAccessStack.pop();
final boolean durationToRight = isDuration( rightOperand.getNodeType() );
final var temporalTypeToLeft = getSqlTemporalType( leftOperandType );
final var temporalTypeToRight = getSqlTemporalType( rightOperandType );
final boolean temporalTypeSomewhereToLeft = adjustedTimestamp != null || temporalTypeToLeft != null;
if ( temporalTypeToLeft != null && durationToRight ) {
if ( adjustmentScale != null || negativeAdjustment ) {
//we can't distribute a scale over a date/timestamp
throw new SemanticException( "Scalar multiplication of temporal value" );
}
}
if ( durationToRight && temporalTypeSomewhereToLeft ) {
return transformDurationArithmetic( expression );
}
else if ( temporalTypeToLeft != null && temporalTypeToRight != null ) {
return transformDatetimeArithmetic( expression );
}
else {
// Infer one operand type through the other
inferrableTypeAccessStack.push( () -> determineValueMapping( rightOperand, fromClauseIndex ) );
final var lhs = toSqlExpression( leftOperand.accept( this ) );
inferrableTypeAccessStack.pop();
inferrableTypeAccessStack.push( () -> determineValueMapping( leftOperand, fromClauseIndex ) );
final var rhs = toSqlExpression( rightOperand.accept( this ) );
inferrableTypeAccessStack.pop();
View on GitHub (pinned to fad1729dce)
Solutions
- Scale the duration, not the timestamp: '(ts1 - ts2) * 2 by second'
- Move the multiplier so the temporal value is only ever added to or subtracted from a duration
- Use duration literals ('2 day') or functions instead of raw scalar multiplication on temporals
Example fix
// before select e.ts * 2 from Event e // after select (e.endTs - e.ts) * 2 from Event e
Defensive patterns
Strategy: validation
Validate before calling
// In query builders: reject arithmetic where a temporal path is multiplied/divided
if (isTemporalPath(leftPath) && (operator == '*' || operator == '/')) {
throw new IllegalArgumentException("Cannot scale a temporal value; scale the duration (ts1 - ts2) instead");
} Try / catch
try {
return session.createQuery(hql).getResultList();
} catch (org.hibernate.query.SemanticException e) {
log.error("Temporal arithmetic rejected: {}", hql, e);
throw e;
} Prevention
- Apply * and / only to durations, never to timestamps
- Write duration math as (end - start) * scale by unit
- Add unit tests for every generated temporal expression
When it happens
Trigger: HQL like 'current_timestamp * 2', 'e.eventTs * :factor', or expressions where a temporal value ends up on the left of a scaled duration operation such as '2 * (ts - other) * 3' after distribution.
Common situations: Porting date math from languages/databases that allow scaling timestamps; report queries computing weighted time offsets; generated queries that wrap whole arithmetic trees in multipliers.
Related errors
- Illegal operator for a duration {}
- Illegal operator for temporal type: {}
- 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/9d2aa5aaa2e812b3.
Report an issue: GitHub.