hibernate/hibernate-orm · error · UnsupportedOperationException
Cannot apply `countDistinct()` to predicates
Error message
Cannot apply `countDistinct()` to predicates
What it means
AbstractSqmPredicate.countDistinct throws UnsupportedOperationException for the same reason as count(): COUNT(DISTINCT ...) is an aggregate over an expression producing values per row, and a predicate is a boolean condition, not a per-row value expression. The method is inherited from JpaExpression's interface surface, so it is visible on predicates, but Hibernate's predicate base class rejects it at build time.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/predicate/AbstractSqmPredicate.java:78
}
@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 );
}
@Nonnull
@Override
public SqmBooleanExpression nullif(@Nonnull Expression<? extends Boolean> y) {
return (SqmBooleanExpression) super.nullif( y );View on GitHub (pinned to fad1729dce)
Solutions
- Count distinct values of a path under the predicate: `query.select( cb.countDistinct( root.get("x")) ).where( predicate )`
- For CASE-based distinct counts, apply countDistinct() to the case expression, not the predicate
- Type-guard generic code: skip or throw your own clear error when the node is a JpaPredicate
- Verify the intended SQL first — COUNT(DISTINCT <boolean>) is almost never what the requirement means
Example fix
// before
JpaPredicate active = cb.isTrue( root.get("active") );
expr = active.countDistinct(); // UnsupportedOperationException
// after
query.select( cb.countDistinct( root.get("department") ) ).where( active ); Defensive patterns
Strategy: type-guard
Validate before calling
if (expr instanceof org.hibernate.query.criteria.JpaPredicate) {
throw new IllegalArgumentException("countDistinct() not applicable to predicates");
} Type guard
static boolean isCountable(org.hibernate.query.criteria.JpaExpression<?> e) {
return !(e instanceof org.hibernate.query.criteria.JpaPredicate);
} Prevention
- Use cb.countDistinct(path) in the select list with the predicate as where
- Apply countDistinct to value expressions only
- Guard generic aggregation wrappers with a predicate type check
When it happens
Trigger: Calling `predicate.countDistinct()` — e.g. `cb.equal( root.get("status"), "A" ).countDistinct()`; generic distinct-count builders applying countDistinct() to Expression<?> without type checks; attempts to emulate COUNT(DISTINCT CASE WHEN ... THEN x END) by counting the predicate itself.
Common situations: Distinct-count reporting code paths that handle all expressions uniformly; porting SQL like `count(distinct (a=b))` to criteria; wrapper APIs exposing countDistinct() on every node descending from JpaExpression.
Related errors
- Cannot apply `count()` 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/79504201924dc65d.
Report an issue: GitHub.