hibernate/hibernate-orm · error · UnsupportedOperationException

isNotMember() is not supported for SqmSubQuery

Error message

isNotMember() is not supported for SqmSubQuery

What it means

JpaExpression inherits isNotMember(Expression<Collection>) but a subquery is a query node, not an element that can be tested for collection membership, so SqmSubQuery implements it to always throw UnsupportedOperationException. The negated membership predicate must be built with CriteriaBuilder.isNotMember(element, collection), which accepts any expression, including a subquery.

Source

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

		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 ) );
	}

	@Override
	public @Nullable SqmBindableType<T> getNodeType() {
		return expressibleType;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Create the predicate via the builder: cb.isNotMember(subquery, collectionPath)
  2. In generic code, branch on 'expression instanceof JpaSubQuery' before invoking expression-level membership methods
  3. For 'value NOT IN (subquery)' semantics, use cb.in(...).value(subquery).not() instead

Example fix

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

// after
Predicate p = cb.isNotMember(sub, orderRoot.get("tags"));
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

static Predicate notMemberOf(CriteriaBuilder cb, Expression<?> elem, Expression<? extends Collection<?>> coll) { return cb.isNotMember(elem, coll); }

Try / catch

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

Prevention

When it happens

Trigger: Calling subquery.isNotMember(collectionExpression) — typically from generic predicate factories that uniformly call isNotMember on Expression<T> when T matches the collection element type.

Common situations: Specification/filter DSLs that dispatch on expression type; negated membership checks generated reflectively; code migrated from literal- or path-based expressions where the call worked.

Related errors


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