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

  1. Scale the duration, not the timestamp: '(ts1 - ts2) * 2 by second'
  2. Move the multiplier so the temporal value is only ever added to or subtracted from a duration
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/9d2aa5aaa2e812b3. Report an issue: GitHub.