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
- Wrap the query: compute the function in an inner SELECT with an alias, then ORDER BY / filter on the alias in the outer query
- Keep the emulated function strictly inside the SELECT list
- 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
- Compute emulated functions in the SELECT list and reference them by alias elsewhere
- Wrap aggregates in a derived table when ordering/filtering on them
- Test report queries on the emulation dialect, not only on PostgreSQL
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
- Can't emulate [%s] in clause %s. Only the SELECT clause is s
- Can't emulate filter clause for inverse distribution functio
- Inverse distribution function '%s' must specify 'WITHIN GROU
- MODE function requires a WITHIN GROUP clause with exactly on
- Could not resolve sort expression: '${sortExpression}'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d3b4280e72f07322.
Report an issue: GitHub.