hibernate/hibernate-orm · error · SemanticException

Operand of " + op.getOperatorChar() + " is of type '" + node

Error message

Operand of " + op.getOperatorChar() + " is of type '" + nodeType.getTypeName() + "' which is not a numeric type (its JDBC type code is not numeric)

What it means

Unary plus/minus in HQL is validated by TypecheckUtil.assertNumeric (SemanticQueryBuilder:3813): the operand's JDBC type must be numeric. Applying `-x` to a String, Boolean, enum, UUID, or date attribute fails this SemanticException during parsing.

Source

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

	public static void assertDuration(SqmExpression<?> expression) {
		final var nodeType = expression.getNodeType();
		if ( nodeType != null ) {
			if ( !( nodeType.getSqmType() instanceof JdbcMapping jdbcMapping )
					|| !jdbcMapping.getJdbcType().isDuration() ) {
				throw new SemanticException(
						"Operand of 'by' is of type '" + nodeType.getTypeName() +
								"' which is not a duration (its JDBC type code is not duration-like)"
				);
			}
		}
	}

	public static void assertNumeric(SqmExpression<?> expression, UnaryArithmeticOperator op) {
		final var nodeType = expression.getExpressible();
		if ( nodeType != null ) {
			if ( !( nodeType.getSqmType() instanceof JdbcMapping jdbcMapping )
					|| !jdbcMapping.getJdbcType().isNumber() ) {
				throw new SemanticException(
						"Operand of " + op.getOperatorChar() + " is of type '" + nodeType.getTypeName() +
								"' which is not a numeric type (its JDBC type code is not numeric)"
				);
			}
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Sort descending with `order by e.x desc` instead of negation
  2. Negate only numeric attributes; cast genuinely numeric strings first: `-cast(e.code as integer)`
  3. In dynamic sort code, verify the attribute type is numeric before emitting a unary '-'

Example fix

// before (priority is an enum)
order by -e.priority

// after
order by e.priority desc
Defensive patterns

Strategy: validation

Validate before calling

// Dynamic sort inversion: negate only numeric attributes, else use desc
SingularAttribute<?, ?> attr = mm.entity(Task.class).getSingularAttribute(sortField);
String order = Number.class.isAssignableFrom(attr.getJavaType())
    ? "order by -e." + sortField
    : "order by e." + sortField + " desc";

Type guard

static boolean isNumericAttr(Attribute<?, ?> a) {
    return Number.class.isAssignableFrom(a.getJavaType());
}

Try / catch

try {
    return em.createQuery(hql).getResultList();
} catch (org.hibernate.query.SemanticException e) {
    throw new QueryBuildException("Unary '-' requires a numeric operand: " + hql, e);
}

Prevention

When it happens

Trigger: `select -e.name from ...`; `order by -e.priority` where priority is an enum; `-e.flag` (Boolean); dynamic sort builders that prepend '-' to invert the ordering of whatever column was chosen.

Common situations: Generic ORDER BY helpers that fake descending numeric sort by negating the expression; sign-flipping string-encoded numbers; queries that ran on Hibernate 5 because no unary type check existed.

Related errors


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