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 datetime

View on GitHub (pinned to fad1729dce)

Solutions

  1. Combine only duration with duration: `e.warranty - 30 day`
  2. To scale a duration, multiply with the NUMBER on the left: `2 * e.duration`
  3. For date/datetime arithmetic keep the date on the left: `e.dueDate + 3 day`
  4. 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

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


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