hibernate/hibernate-orm · error · IllegalArgumentException

Can't emulate filter clause for inverse distribution functio

Error message

Can't emulate filter clause for inverse distribution function [%s]

What it means

InverseDistributionFunction is the shared renderer for inverse distribution aggregates (percentile_cont, percentile_disc, mode). When a FILTER clause is present and the target dialect's translator does not support FILTER, this renderer has no way to emulate the filter for an inverse distribution function and throws during SQL rendering.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/InverseDistributionFunction.java:99

	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)

Solutions

  1. Move the filter predicate into the WHERE clause of a feeding subquery
  2. Drop FILTER when it can be folded into the main query's WHERE clause
  3. Use native SQL or a FILTER-capable dialect (e.g. PostgreSQL) for that query

Example fix

// before
select mode() within group (order by e.status) filter (where e.tenant = 1) from Event e

// after
select mode() within group (order by t.status) from (select e.status from Event e where e.tenant = 1) t
Defensive patterns

Strategy: fallback

Validate before calling

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, Object.class).getResultList();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("emulate filter clause")) {
        return em.createQuery(hqlWithWhere, Object.class).getResultList();
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL: percentile_disc(0.5) within group (order by x) filter (where cond) or mode() within group (order by x) filter (where cond) on a dialect lacking FILTER support.

Common situations: Analytics HQL with filter clauses moved between databases; CI matrix runs against MySQL-family dialects; dialect upgrades that changed FILTER emulation availability.

Related errors


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