hibernate/hibernate-orm · error · UnsupportedOperationException

isMember() is not supported for SqmSubQuery

Error message

isMember() is not supported for SqmSubQuery

What it means

JpaExpression inherits isMember(Expression<Collection>) from the expression API, but a subquery is not a value that can be a member of a collection — it is a query node. SqmSubQuery therefore implements isMember to always throw UnsupportedOperationException. Membership predicates must be created through the CriteriaBuilder (cb.isMember(element, collection)) so that Hibernate can build the correct SQL.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/select/SqmSubQuery.java:769

	public SqmCriteriaNodeBuilder nodeBuilder() {
		return (SqmCriteriaNodeBuilder) super.nodeBuilder();
	}

	@Override
	public <R> SqmCaseSimple<T, R> selectCase() {
		return nodeBuilder().selectCase( this );
	}

	@Nonnull
	@Override
	public <R> SqmCaseSimple<T, R> selectCase(@Nonnull Class<R> resultType) {
		return nodeBuilder().selectCase( this, resultType );
	}

	@Nonnull
	@Override
	public SqmPredicate isMember(@Nonnull Expression<? extends Collection<? super T>> collection) {
		throw new UnsupportedOperationException( "isMember() is not supported for SqmSubQuery" );
	}

	@Nonnull
	@Override
	public JpaPredicate isNotMember(@Nonnull Expression<? extends Collection<? super T>> collection) {
		throw new UnsupportedOperationException( "isNotMember() is not supported for SqmSubQuery" );
	}

	@Nonnull
	@Override
	public SqmNumericExpression<Long> count() {
		return new SqmNumericExpressionWrapper<>( nodeBuilder().count( this ) );
	}

	@Nonnull
	@Override
	public SqmNumericExpression<Long> countDistinct() {
		return new SqmNumericExpressionWrapper<>( nodeBuilder().countDistinct( this ) );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Create the predicate via the builder: cb.isMember(subquery, collectionPath) — the two-arg CriteriaBuilder method accepts any expression including subqueries
  2. In generic code, check 'expression instanceof JpaSubQuery' (or SqmSubQuery) before calling instance methods and route subqueries to builder methods
  3. If you meant 'value IN (subquery)', use cb.in(...) / subquery-in predicates instead of isMember

Example fix

// before
Subquery<Long> sub = query.subquery(Long.class);
Predicate p = sub.isMember(orderRoot.get("tags")); // UnsupportedOperationException

// after
Predicate p = cb.isMember(sub, orderRoot.get("tags")); // builder-created predicate
Defensive patterns

Strategy: type-guard

Validate before calling

if (expr instanceof JpaSubQuery<?>) { p = cb.isMember(expr, collection); } else { p = expr.isMember(collection); }

Type guard

static Predicate memberOf(CriteriaBuilder cb, Expression<?> elem, Expression<? extends Collection<?>> coll) { return cb.isMember(elem, coll); } // safe for any expression kind

Try / catch

try { p = expr.isMember(coll); } catch (UnsupportedOperationException e) { if (e.getMessage().contains("isMember")) p = cb.isMember(expr, coll); else throw e; }

Prevention

When it happens

Trigger: Calling subquery.isMember(collectionExpression) — usually from generic predicate factories that call isMember on any Expression<T> when T matches the collection element type, or from copy-adapted code that treats all expressions uniformly.

Common situations: Generic filter/specification builders (Spring Data JPA-like Specs) that dispatch on expression types; code ported from places where the expression was a literal or path; metaprogrammed predicate generation.

Related errors


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