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', 'java.time.Temporal', or 'java.time.TemporalAmount')

What it means

This is the catch-all branch of assertOperable: the LEFT operand of a binary arithmetic operator must be a Number, Temporal, java.util.Date, TemporalAmount, or numeric array. Strings, booleans, enums, UUIDs, byte[], and non-numeric arrays all fall through and the query fails with this SemanticException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java:595

						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 ( isNumberArray( leftNodeType ) ) {
				// left operand is a number
				if ( !isNumberArray( rightNodeType ) ) {
					throw new SemanticException(
							"Operand of " + op.getOperatorSqlText() + " is of type '" + rightNodeType.getTypeName() +
									"' which is not a numeric array type" + " (it is not an instance of 'java.lang.Number[]')"
					);
				}
			}
			else {
				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', 'java.time.Temporal', or 'java.time.TemporalAmount')"
				);
			}
		}
	}

	public static boolean isNumberArray(@Nullable SqmExpressible<?> expressible) {
		if ( expressible != null ) {
			final var domainType = expressible.getSqmType();
			if ( domainType != null ) {
				return domainType instanceof BasicPluralType<?, ?> basicPluralType
					&& Number.class.isAssignableFrom( basicPluralType.getElementType().getJavaType() );
			}
		}
		return false;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use `concat(e.firstName, ' ', e.lastName)` or `e.firstName || ' ' || e.lastName` for strings
  2. Cast genuinely numeric content stored as text: `cast(e.code as integer) + 1`
  3. Remove arithmetic from boolean/enum/UUID attributes; express those conditions as comparisons
  4. For enums use `cast(e.status as integer)` when you need the ordinal numerically

Example fix

// before
where e.firstName + ' ' + e.lastName = :fullName

// after
where concat(e.firstName, ' ', e.lastName) = :fullName
Defensive patterns

Strategy: try-catch

Validate before calling

// Generic search filter: only allow 'like'/'concat' paths on non-numeric fields
SingularAttribute<?, ?> attr = mm.entity(Person.class).getSingularAttribute(field);
if (!String.class.equals(attr.getJavaType())
        && !Number.class.isAssignableFrom(attr.getJavaType())) {
    throw new IllegalArgumentException("Arithmetic unsupported for field " + field);
}

Type guard

static boolean supportsArithmetic(Class<?> c) {
    return Number.class.isAssignableFrom(c)
        || java.time.temporal.TemporalAmount.class.isAssignableFrom(c)
        || java.time.temporal.Temporal.class.isAssignableFrom(c)
        || java.util.Date.class.isAssignableFrom(c);
}

Try / catch

try {
    return em.createQuery(hql).getResultList();
} catch (org.hibernate.query.SemanticException e) {
    throw new QueryBuildException(
        "Left operand not arithmetic-capable — use concat() for strings: " + hql, e);
}

Prevention

When it happens

Trigger: `e.firstName + ' ' + e.lastName` (string concatenation with '+'); `e.active + 1` (Boolean); `e.status + 1` (enum); `e.tags + e.labels` (String[] + String[]); arithmetic on a UUID or JSON attribute.

Common situations: The single most common hit: SQL habits where '+' concatenates strings — JPQL/HQL require concat() or ||; generic search builders arithmetic-ing whatever field was supplied; upgrading to Hibernate 6.3+ (HHH-15345 era) where these checks became strict and previously-tolerated queries now fail.

Related errors


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