{"record":{"id":"bed8cc0d2ff024b5","repo":"hibernate/hibernate-orm","slug":"boolean-expression-does-not-support-min","errorCode":null,"errorMessage":"Boolean expression does not support min()","messagePattern":"Boolean expression does not support min\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBooleanValuedSimplePath.java","lineNumber":89,"sourceCode":"\t\treturn new SqmBooleanExpressionWrapper( nodeBuilder().nullif( this, y ) );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmBooleanExpression nullif(Boolean y) {\n\t\treturn new SqmBooleanExpressionWrapper( nodeBuilder().nullif( this, y ) );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmBooleanExpression max() {\n\t\tthrow new UnsupportedOperationException( \"Boolean expression does not support max()\" );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmBooleanExpression min() {\n\t\tthrow new UnsupportedOperationException( \"Boolean expression does not support min()\" );\n\t}\n}\n","sourceCodeStart":71,"sourceCodeEnd":92,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBooleanValuedSimplePath.java#L71-L92","documentation":"SqmBooleanValuedSimplePath.min() is the mirror of max(): the min aggregate requires an orderable scalar type and Hibernate throws UnsupportedOperationException when .min() is invoked on a boolean-valued path. Like its sibling it fails during SQM construction, not at SQL execution. The message names min() explicitly.","triggerScenarios":"HQL \"select min(e.deleted) from Document d\" where deleted is boolean; Criteria code calling .min() on root.get(\"enabled\") of a Boolean attribute; generic min/max toggle in a query builder applied to a flag column.","commonSituations":"Dashboards computing 'all rows still enabled' as min(flag); T-SQL/MySQL-style boolean aggregate habits carried into HQL; soft-delete flags aggregated with min() to check whether any row is deleted.","solutions":["Cast before aggregating: \"select min(cast(e.deleted as int)) from Document d\" or cb.min(cb.toInteger(root.get(\"deleted\"))).","Express the intent directly: \"select count(d) from Document d where d.deleted = false\" or an every()/case-based predicate.","Filter generic aggregation UIs to Number-typed expressions only.","If native SQL min() on a boolean column is unavoidable, use a native query where the dialect decides."],"exampleFix":"// before - deleted is boolean -> UnsupportedOperationException\nLong r = em.createQuery(\"select min(cast(e.deleted as boolean)) from Document e\", Long.class).getSingleResult();\n\n// after - aggregate the integer cast\nInteger r = em.createQuery(\"select min(cast(e.deleted as int)) from Document e\", Integer.class).getSingleResult();","handlingStrategy":"validation","validationCode":"static boolean minSupported(jakarta.persistence.criteria.Expression<?> e) {\n    Class<?> t = e.getJavaType();\n    if (t == null) return false;\n    if (Boolean.class == t || boolean.class == t) return false; // min() unsupported on boolean\n    return Number.class.isAssignableFrom(t) || t.isPrimitive()\n        || java.time.temporal.Temporal.class.isAssignableFrom(t) || String.class == t;\n}","typeGuard":"static boolean isBooleanExpr(jakarta.persistence.criteria.Expression<?> e) {\n    return Boolean.class == e.getJavaType() || boolean.class == e.getJavaType();\n}","tryCatchPattern":"try {\n    return cb.min(expr);\n} catch (UnsupportedOperationException e) {\n    if (Boolean.class == expr.getJavaType()) {\n        return cb.min(cb.toInteger((jakarta.persistence.criteria.Expression<Boolean>) expr));\n    }\n    throw e;\n}","preventionTips":["Express 'all rows satisfy flag' as a count/where predicate, not min(flag).","Keep a type allowlist for aggregate-able expressions in query-builder UIs.","Cast boolean columns to int in HQL before min/max."],"tags":["hibernate","hql","criteria-api","aggregate","boolean","sqm"],"backgroundTag":"aggregate-on-boolean","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}