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
- Count rows matching the predicate: `query.select( cb.count( root ) ).where( predicate )`
- For conditional aggregation use `cb.sum( cb.<Long>selectCase().when(predicate, 1L).otherwise(0L) )`
- In generic code, check `!(expr instanceof JpaPredicate)` before calling count()/countDistinct()
- 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
- Reach for cb.count(path) with the predicate in where() — never predicate.count()
- Narrow Expression<?> nodes before calling aggregate methods
- For conditional aggregates use sum(case) instead of count(predicate)
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
- Cannot apply `countDistinct()` to predicates
- Dialect does not support structured array types: ${dialectCl
- DELETE query cannot be sub-query
- Boolean expression does not support max()
- Boolean expression does not support min()
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/25f589a1fb7d831e.
Report an issue: GitHub.