hibernate/hibernate-orm · error · SemanticException
Cannot compare left expression of type '%s' with right expre
Error message
Cannot compare left expression of type '%s' with right expression of type '%s'
What it means
SqmMemberOfPredicate's constructor throws SemanticException when the left-hand expression of a MEMBER OF test is not type-comparable with the element type of the plural path. Hibernate resolves the collection's element type (`pluralPath.getPluralAttribute().getElementType()`) and runs TypecheckUtil.areTypesComparable against the left expression's node type; `x member of y` is only valid when x could be an element of y (same type, or comparable basic/super/sub type). The check fails fast during SQM construction.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/predicate/SqmMemberOfPredicate.java:47
public SqmMemberOfPredicate(SqmExpression<?> leftHandExpression, SqmPluralValuedSimplePath<?> pluralPath, NodeBuilder nodeBuilder) {
this( leftHandExpression, pluralPath, false, nodeBuilder );
}
public SqmMemberOfPredicate(
SqmExpression<?> leftHandExpression,
SqmPluralValuedSimplePath<?> pluralPath,
boolean negated,
NodeBuilder nodeBuilder) {
super( negated, nodeBuilder );
this.pluralPath = pluralPath;
this.leftHandExpression = leftHandExpression;
final SimpleDomainType<?> elementType = pluralPath.getPluralAttribute().getElementType();
final SqmBindableType<?> simpleDomainType = nodeBuilder.resolveExpressible( elementType );
if ( !areTypesComparable( leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder ) ) {
throw new SemanticException(
String.format(
"Cannot compare left expression of type '%s' with right expression of type '%s'",
castNonNull( leftHandExpression.getNodeType() ).getTypeName(),
pluralPath.getNodeType().getTypeName()
)
);
}
leftHandExpression.applyInferableType( simpleDomainType );
}
@Override
public SqmMemberOfPredicate copy(SqmCopyContext context) {
final SqmMemberOfPredicate existing = context.getCopy( this );
if ( existing != null ) {
return existing;
}
final SqmMemberOfPredicate predicate = context.registerCopy(View on GitHub (pinned to fad1729dce)
Solutions
- Make the left expression's type match the collection element type — check `pluralPath.getPluralAttribute().getElement().getJavaType()`
- For element collections of basics, compare the basic value: `where 'x' member of p.tags`
- For entity collections, use the entity-typed path/parameter: `where :order member of customer.orders`
- If you meant scalar containment over a basic collection, use `path in (...)` against the collection instead of member of
Example fix
// before
// Order.lines is List<OrderLine> (entity elements)
session.createQuery("from Order o where 1 member of o.lines", Order.class); // SemanticException
// after
session.createQuery("from Order o where :line member of o.lines", Order.class)
.setParameter("line", lineRef); Defensive patterns
Strategy: validation
Validate before calling
import jakarta.persistence.metamodel.PluralAttribute;
Class<?> elementType = ((PluralAttribute<?, ?, ?>) path.getModel()).getElementType().getJavaType();
if (!elementType.isAssignableFrom(leftExpr.getJavaType())) {
throw new IllegalArgumentException("MEMBER OF left side must be " + elementType + ", got " + leftExpr.getJavaType());
}
cb.isMember(leftExpr, path); Try / catch
try { session.createQuery(hql).list(); }
catch (org.hibernate.query.SemanticException e) {
// 'Cannot compare left expression...' -> fix the left-side type in the query string
throw e;
} Prevention
- Check the collection's element type before isMember/member of
- After changing an element collection's type, grep for member of on that path
- Prefer entity-typed references for entity collections; basics for element collections
When it happens
Trigger: HQL `where 1 member of p.names` where names is Collection<String>; `where p.id member of o.lines` (Long vs OrderLine); criteria `cb.isMember( cb.literal(1), person.get("names") )`; binding a parameter of the wrong Java type via `setParameter` when the left expression is an untyped parameter whose inferred type mismatches the element type.
Common situations: Copying MEMBER OF from SQL IN intuitions (IN compares scalars, MEMBER OF compares entities/elements with collections); schema refactors that changed an element collection's element type (String → enum, Long → UUID) while old queries remain; passing the entity itself instead of its id, or the id instead of the entity, on either side.
Related errors
- Root path treats can not be aliased - " + getNavigablePath()
- Root path treats can not be fetched - " + getNavigablePath()
- Expected insert attribute count [%d] did not match Query sel
- Parameter %d of function '%s()' has type '%s', but argument
- NATIVE is not a legal field for extract()
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/13809c5c6c2214d6.
Report an issue: GitHub.