{"record":{"id":"e89a7500c61bd1a1","repo":"hibernate/hibernate-orm","slug":"boolean-expression-does-not-support-max-e89a75","errorCode":null,"errorMessage":"Boolean expression does not support max()","messagePattern":"Boolean expression does not support max\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmBooleanExpressionWrapper.java","lineNumber":59,"sourceCode":"\t\treturn new SqmBooleanExpressionWrapper( nodeBuilder().coalesce( this, y ) );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmBooleanExpression nullif(@Nonnull Expression<? extends Boolean> y) {\n\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\t@Override\n\tpublic SqmExpression<Boolean> copy(SqmCopyContext context) {\n\t\treturn wrappedExpression.copy( context );\n\t}\n\n\t@Override\n\tpublic void appendHqlString(StringBuilder hql, SqmRenderContext context) {\n\t\twrappedExpression.appendHqlString( hql, context );\n\t}\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmBooleanExpressionWrapper.java#L41-L77","documentation":"SqmBooleanExpressionWrapper adapts an arbitrary SQM expression to the Boolean expression API (e.g. results of nodeBuilder().wrapExpressionAsBoolean or boolean-producing operations). Its max() throws UnsupportedOperationException('Boolean expression does not support max()') because Boolean aggregation is not representable in the SQM type system.","triggerScenarios":"Calling .max() on an expression wrapped into the Boolean API: cb.wrapExpressionAsBoolean(expr).max(), or operations that return SqmBooleanExpression (nullif/Coalesce over booleans) followed by .max().","commonSituations":"Fluent criteria pipelines that wrap then aggregate; aggregation helpers receiving already-wrapped boolean expressions; queries generating per-group boolean rollups.","solutions":["Aggregate a numeric encoding instead: wrap the aggregate, not the boolean — cb.max(cb.selectCase().when(cb.isTrue(wrapped), 1).otherwise(0)).","Use cb.sum over the case encoding when you need a count of true values.","Perform the rollup in native SQL if the dialect supports boolean aggregates.","Keep a type check in generic aggregation code: skip max()/min() for Boolean-typed expressions."],"exampleFix":"// before\nSqmBooleanExpression flag = (SqmBooleanExpression) cb.wrapExpressionAsBoolean(root.get(\"active\"));\nquery.select(flag.max()); // UnsupportedOperationException\n// after\nquery.select(cb.sum(cb.selectCase().when(cb.isTrue(root.get(\"active\")), 1).otherwise(0)));","handlingStrategy":"type-guard","validationCode":"static boolean numeric(Expression<?> e) {\n    return e.getJavaType() != null && Number.class.isAssignableFrom(e.getJavaType());\n}\n// wrapped boolean expressions: skip max(); aggregate a case-to-int projection instead","typeGuard":"static boolean aggregatableByMinMax(Expression<?> e) {\n    Class<?> jt = e.getJavaType();\n    return jt != null && Number.class.isAssignableFrom(jt);\n}","tryCatchPattern":null,"preventionTips":["Do not wrap-then-aggregate booleans; build the numeric projection first, then wrap if needed.","Centralize aggregation behind one helper that checks expression Java type.","Cover boolean rollup queries with tests against H2/embedded DB to catch them early."],"tags":["hibernate","criteria-api","aggregation","boolean","wrapper","unsupported-operation"],"backgroundTag":"min-max-on-non-numeric-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}