hibernate/hibernate-orm · error · UnsupportedOperationException

Cannot apply `count()` to predicates

Error message

Cannot apply `count()` to predicates

What it means

AbstractSqmPredicate.count throws UnsupportedOperationException because predicates in the criteria tree are not value expressions — COUNT() is an aggregate over rows/expressions, and applying it to a boolean predicate node has no SQL meaning. Hibernate exposes count()/countDistinct() on JpaExpression, and JpaPredicate inherits the signatures, but the predicate base implementation explicitly rejects them so misuse fails at statement-build time rather than generating garbage SQL.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/predicate/AbstractSqmPredicate.java:72

	@Nonnull
	@Override
	public BooleanOperator getOperator() {
		// most predicates are conjunctive
		return BooleanOperator.AND;
	}

	@Nonnull
	@Override
	public List<Expression<Boolean>> getExpressions() {
		/// most predicates do not have sub-predicates
		return new ArrayList<>(0);
	}

	@Nonnull
	@Override
	public JpaNumericExpression<Long> count() {
		throw new UnsupportedOperationException( "Cannot apply `count()` to predicates" );
	}

	@Nonnull
	@Override
	public JpaNumericExpression<Long> countDistinct() {
		throw new UnsupportedOperationException( "Cannot apply `countDistinct()` to predicates" );
	}

	@Nonnull
	@Override
	public SqmBooleanExpression coalesce(@Nonnull Expression<? extends Boolean> y) {
		return (SqmBooleanExpression) super.coalesce( y );
	}

	@Nonnull
	@Override
	public SqmBooleanExpression coalesce(Boolean y) {
		return (SqmBooleanExpression) super.coalesce( y );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Count rows matching the predicate: `query.select( cb.count( root ) ).where( predicate )`
  2. For conditional aggregation use `cb.sum( cb.<Long>selectCase().when(predicate, 1L).otherwise(0L) )`
  3. In generic code, check `!(expr instanceof JpaPredicate)` before calling count()/countDistinct()
  4. Bind the predicate into the WHERE clause and aggregate over a real path expression

Example fix

// before
Predicate isActive = cb.isTrue( root.get("active") );
expr = ((JpaExpression<?>) isActive).count(); // UnsupportedOperationException

// after
query.select( cb.count( root ) ).where( isActive );
Defensive patterns

Strategy: type-guard

Validate before calling

import org.hibernate.query.criteria.JpaPredicate;

if (expr instanceof JpaPredicate) {
    throw new IllegalArgumentException("count() not applicable to predicates; move it to the WHERE clause");
}

Type guard

static boolean isCountable(org.hibernate.query.criteria.JpaExpression<?> e) {
    return !(e instanceof org.hibernate.query.criteria.JpaPredicate);
}

Prevention

When it happens

Trigger: Calling `predicate.count()` on any JpaPredicate/SqmPredicate — e.g. `cb.isNull( path ).count()`, or `cb.and( p1, p2 ).count()`; generic reporting code that wraps arbitrary expressions with count(); dynamic code that receives Expression<?> and calls count() without narrowing.

Common situations: Trying to build `SELECT COUNT(CASE WHEN ... )`-style aggregates and reaching for predicate.count() instead of cb.count/cb.sum; generic column-aggregation layers that apply count() to whatever node they hold; confusion caused by count() being visible on predicates via the interface hierarchy.

Related errors


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