hibernate/hibernate-orm · error · IllegalArgumentException
Can't emulate filter clause for inverse distribution…
Error message
Can't emulate filter clause for inverse distribution function [%s]
What it means
HypotheticalSetFunction renders ordered-set aggregates (percentile_cont, percentile_disc and friends). The SQL FILTER clause on aggregates cannot always be translated: when a filter predicate is present and the target dialect's translator does not support the FILTER clause, this renderer has no emulation for hypothetical set functions and throws during SQL rendering.
Solutions
- Move the FILTER predicate into the WHERE clause of the subquery feeding the aggregate
- Select the filtered rows in a derived table and apply the ordered-set aggregate on top of it
- Drop FILTER when the semantics allow folding it into the main WHERE clause
- Run the query as native SQL, or target a dialect with native FILTER support
Example fix
// before select percentile_cont(0.5) within group (order by s.amount) filter (where s.status = 'OK') from Sale s // after select percentile_cont(0.5) within group (order by t.amount) from ( select s.amount as amount from Sale s where s.status = 'OK' ) t
Defensive patterns
Strategy: fallback
Validate before calling
// Only use FILTER on ordered-set aggregates for translators that support the clause
boolean filterSupported(SessionFactory sf) {
String dialect = sf.getJdbcServices().getDialect().getClass().getSimpleName();
return dialect.contains("PostgreSQL") || dialect.contains("H2"); // extend per your verified matrix
} Try / catch
try {
return em.createQuery(hqlWithFilter, Double.class).getResultList();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("emulate filter clause")) {
// predicate moved from FILTER into the feeding subquery's WHERE
return em.createQuery(hqlWithWhere, Double.class).getResultList();
}
throw e;
} Prevention
- Prefer WHERE over FILTER in HQL meant to be portable
- Maintain a per-dialect capability matrix in integration tests for ordered-set aggregates
- Run analytics HQL against every target dialect in CI
When it happens
Trigger: HQL: percentile_cont(0.5) within group (order by x) filter (where e.type = 'A') executed on a dialect that reports no FILTER support (typical MySQL/MariaDB bases without native FILTER).
Common situations: Porting analytics HQL from PostgreSQL to MySQL-family databases; using HQL filter clauses generated by query DSLs; upgrading a dialect where FILTER emulation was previously absent but tolerated.
Related errors
- Can't emulate filter clause for inverse distribution…
- Can't emulate [ ] in clause . Only the SELECT clause is…
- Inverse distribution function
- MODE function requires a WITHIN GROUP clause with exactly…
- The function is not an aggregate function
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/855aabf67bc812d9.
Report an issue: GitHub.
Appendix: source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/HypotheticalSetFunction.java:68
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
Predicate filter,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
render( sqlAppender, sqlAstArguments, filter, Collections.emptyList(), returnType, walker );
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
Predicate filter,
List<SortSpecification> withinGroup,
ReturnableType<?> returnType,
SqlAstTranslator<?> translator) {
if ( filter != null && !filterClauseSupported( translator ) ) {
throw new IllegalArgumentException( "Can't emulate filter clause for inverse distribution function [" + getName() + "]" );
}
sqlAppender.appendSql( getName() );
sqlAppender.appendSql( '(' );
if ( !sqlAstArguments.isEmpty() ) {
sqlAstArguments.get( 0 ).accept( translator );
for ( int i = 1; i < sqlAstArguments.size(); i++ ) {
sqlAppender.append( ',' );
sqlAstArguments.get( i ).accept( translator );
}
}
sqlAppender.appendSql( ')' );
if ( withinGroup != null && !withinGroup.isEmpty() ) {
translator.getCurrentClauseStack().push( Clause.WITHIN_GROUP );
sqlAppender.appendSql( " within group (order by " );
withinGroup.get( 0 ).accept( translator );
for ( int i = 1; i < withinGroup.size(); i++ ) {
sqlAppender.appendSql( ',' );
withinGroup.get( i ).accept( translator );View on GitHub (pinned to fad1729dce)