hibernate/hibernate-orm · error · IllegalArgumentException

Can't emulate [%s] in clause %s. Only the SELECT clause is s

Error message

Can't emulate [%s] in clause %s. Only the SELECT clause is supported

What it means

On dialects without native ordered-set aggregate support Hibernate emulates hypothetical set functions by inlining a scalar subquery. That emulation only knows how to place the subquery in the SELECT clause or an OVER window; referencing the function in any other clause (WHERE, GROUP BY, HAVING, ORDER BY, ...) is rejected at SQM-to-SQL conversion.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/HypotheticalSetWindowEmulation.java:72

				this,
				arguments,
				filter,
				withinGroupClause,
				impliedResultType,
				getArgumentsValidator(),
				getReturnTypeResolver(),
				queryEngine.getCriteriaBuilder(),
				getName()
		) {

			@Override
			public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
				final Clause currentClause = walker.getCurrentClauseStack().getCurrent();
				if ( currentClause == Clause.OVER ) {
					return super.convertToSqlAst( walker );
				}
				else if ( currentClause != Clause.SELECT ) {
					throw new IllegalArgumentException( "Can't emulate [" + getName() + "] in clause " + currentClause + ". Only the SELECT clause is supported" );
				}
				final ReturnableType<?> resultType = resolveResultType( walker );

				List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
				ArgumentsValidator argumentsValidator = getArgumentsValidator();
				if ( argumentsValidator != null ) {
					argumentsValidator.validateSqlTypes( arguments, getFunctionName() );
				}
				List<SortSpecification> withinGroup;
				if ( this.getWithinGroup() == null ) {
					withinGroup = emptyList();
				}
				else {
					walker.getCurrentClauseStack().push( Clause.ORDER );
					try {
						final List<SqmSortSpecification> sortSpecifications = this.getWithinGroup().getSortSpecifications();
						withinGroup = new ArrayList<>( sortSpecifications.size() );
						for ( SqmSortSpecification sortSpecification : sortSpecifications ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Wrap the query: compute the function in an inner SELECT with an alias, then ORDER BY / filter on the alias in the outer query
  2. Keep the emulated function strictly inside the SELECT list
  3. Use native SQL for that query, or a dialect with native ordered-set aggregate support

Example fix

// before
select e.dept, percentile_cont(0.5) within group (order by e.salary) from Emp e group by e.dept order by percentile_cont(0.5) within group (order by e.salary)

// after
select d.dept, d.med from (
  select e.dept as dept, percentile_cont(0.5) within group (order by e.salary) as med from Emp e group by e.dept
) d order by d.med
Defensive patterns

Strategy: fallback

Validate before calling

// Emulated ordered-set aggregates may only appear in the SELECT list / OVER —
// reject queries that reference them in other clauses before running them
static boolean clauseSafeHql(String hql, String fn) {
    String lower = hql.toLowerCase(java.util.Locale.ROOT);
    int fnAt = lower.indexOf(fn.toLowerCase());
    if (fnAt < 0) return true;
    for (String kw : new String[]{" order by ", " where ", " group by ", " having "}) {
        int kwAt = lower.indexOf(kw);
        if (kwAt >= 0 && lower.indexOf(fn.toLowerCase(), kwAt) >= 0) return false;
    }
    return true;
}

Try / catch

try {
    return em.createQuery(hql, Double.class).getResultList();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("Only the SELECT clause is supported")) {
        // re-issue with the function computed in an inner select and an outer alias reference
        return em.createQuery(wrapInSubquery(hql), Double.class).getResultList();
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL: ... order by percentile_cont(0.5) within group (order by x), or filtering on the function's value in WHERE/GROUP BY/HAVING, on a dialect that emulates the function.

Common situations: Sorting or filtering report queries by a computed percentile; MySQL-family targets where percentile functions are emulated; HQL copied from SELECT-list usage into ORDER BY during refactoring.

Related errors


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