hibernate/hibernate-orm · error · UnsupportedOperationException

max() not supported

Error message

max() not supported

What it means

Hibernate's extended criteria API exposes max() directly on JpaExpression/SqmComparableExpression. Boolean expressions implement SqmBooleanExpressionImplementor, whose default max() throws UnsupportedOperationException because aggregation over Boolean is not defined in the SQM type system — there is no max Boolean basic type or comparable aggregate semantics.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmBooleanExpressionImplementor.java:22

 */
package org.hibernate.query.sqm.tree.spi.expression;

import jakarta.annotation.Nonnull;
import jakarta.persistence.criteria.Expression;
import org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder;
import org.hibernate.query.sqm.tree.spi.predicate.SqmPredicate;

/**
 * @author Steve Ebersole
 */
public interface SqmBooleanExpressionImplementor
		extends SqmComparableExpressionImplementor<Boolean>, SqmBooleanExpression {
	SqmCriteriaNodeBuilder nodeBuilder();

	@Nonnull
	@Override
	default SqmComparableExpression<Boolean> max() {
		throw new UnsupportedOperationException( "max() not supported" );
	}

	@Nonnull
	@Override
	default SqmComparableExpression<Boolean> min() {
		throw new UnsupportedOperationException( "min() not supported" );
	}

	@Nonnull
	@Override
	default SqmPredicate and(@Nonnull Expression<Boolean> y) {
		return nodeBuilder().and( this, y );
	}

	@Nonnull
	@Override
	default SqmPredicate or(@Nonnull Expression<Boolean> y) {
		return nodeBuilder().or( this, y );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Convert to numeric before aggregating: cb.sum(cb.selectCase().when(cb.isTrue(flag), 1).otherwise(0)) for 'count of trues', or max over the same case expression.
  2. For 'any true' semantics use cb.isTrue(cb.max(...)) on the numeric projection or cb.sum(...) > 0.
  3. Change the column mapping to a smallint/int and aggregate that, or handle the aggregation in SQL via native query where the dialect supports it.
  4. Guard generic helpers: only call max() when the expression's Java type is numeric.

Example fix

// before
JpaExpression<Boolean> active = root.get("active");
query.select(active.max()); // UnsupportedOperationException: max() not supported
// after
query.select(cb.sum(cb.selectCase().when(cb.isTrue(root.get("active")), 1).otherwise(0)));
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean numeric(Expression<?> e) {
    return e.getJavaType() != null && Number.class.isAssignableFrom(e.getJavaType());
}
// before aggregating: if (numeric(expr)) ((JpaExpression) expr).max(); else use a case-to-int encoding

Type guard

static boolean aggregatableByMinMax(Expression<?> e) {
    Class<?> jt = e.getJavaType();
    return jt != null && Number.class.isAssignableFrom(jt)
            && !Boolean.class.isAssignableFrom(jt);
}

Prevention

When it happens

Trigger: ((JpaExpression<Boolean>) root.get("active")).max(), booleanPath.max(), or cb.isTrue(...)-derived expressions with .max() chained in Hibernate 6 criteria code.

Common situations: Report queries that aggregate a boolean column ('max of active flag per group'); code migrated from native SQL where the dialect accepted max(boolean); generic aggregation helpers that call max() on whatever expression they are handed.

Related errors


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