{"record":{"id":"13809c5c6c2214d6","repo":"hibernate/hibernate-orm","slug":"cannot-compare-left-expression-of-type-s-with-r-13809c","errorCode":null,"errorMessage":"Cannot compare left expression of type '%s' with right expression of type '%s'","messagePattern":"Cannot compare left expression of type '(.+?)' with right expression of type '(.+?)'","errorType":"exception","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/predicate/SqmMemberOfPredicate.java","lineNumber":47,"sourceCode":"\tpublic SqmMemberOfPredicate(SqmExpression<?> leftHandExpression, SqmPluralValuedSimplePath<?> pluralPath, NodeBuilder nodeBuilder) {\n\t\tthis( leftHandExpression, pluralPath, false, nodeBuilder );\n\t}\n\n\tpublic SqmMemberOfPredicate(\n\t\t\tSqmExpression<?> leftHandExpression,\n\t\t\tSqmPluralValuedSimplePath<?> pluralPath,\n\t\t\tboolean negated,\n\t\t\tNodeBuilder nodeBuilder) {\n\t\tsuper( negated, nodeBuilder );\n\n\t\tthis.pluralPath = pluralPath;\n\t\tthis.leftHandExpression = leftHandExpression;\n\n\t\tfinal SimpleDomainType<?> elementType = pluralPath.getPluralAttribute().getElementType();\n\t\tfinal SqmBindableType<?> simpleDomainType = nodeBuilder.resolveExpressible( elementType );\n\n\t\tif ( !areTypesComparable( leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder ) ) {\n\t\t\tthrow new SemanticException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\"Cannot compare left expression of type '%s' with right expression of type '%s'\",\n\t\t\t\t\t\t\tcastNonNull( leftHandExpression.getNodeType() ).getTypeName(),\n\t\t\t\t\t\t\tpluralPath.getNodeType().getTypeName()\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\tleftHandExpression.applyInferableType( simpleDomainType );\n\t}\n\n\t@Override\n\tpublic SqmMemberOfPredicate copy(SqmCopyContext context) {\n\t\tfinal SqmMemberOfPredicate existing = context.getCopy( this );\n\t\tif ( existing != null ) {\n\t\t\treturn existing;\n\t\t}\n\t\tfinal SqmMemberOfPredicate predicate = context.registerCopy(","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/predicate/SqmMemberOfPredicate.java#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n// Order.lines is List<OrderLine> (entity elements)\nsession.createQuery(\"from Order o where 1 member of o.lines\", Order.class); // SemanticException\n\n// after\nsession.createQuery(\"from Order o where :line member of o.lines\", Order.class)\n        .setParameter(\"line\", lineRef);","handlingStrategy":"validation","validationCode":"import jakarta.persistence.metamodel.PluralAttribute;\n\nClass<?> elementType = ((PluralAttribute<?, ?, ?>) path.getModel()).getElementType().getJavaType();\nif (!elementType.isAssignableFrom(leftExpr.getJavaType())) {\n    throw new IllegalArgumentException(\"MEMBER OF left side must be \" + elementType + \", got \" + leftExpr.getJavaType());\n}\ncb.isMember(leftExpr, path);","typeGuard":null,"tryCatchPattern":"try { session.createQuery(hql).list(); }\ncatch (org.hibernate.query.SemanticException e) {\n    // 'Cannot compare left expression...' -> fix the left-side type in the query string\n    throw e;\n}","preventionTips":["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"],"tags":["hibernate","hql","criteria-api","member-of","type-mismatch","semantic-error"],"backgroundTag":"hql-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}