hibernate/hibernate-orm · error · SemanticException
Could not resolve sort expression: '${sortExpression}'
Error message
Could not resolve sort expression: '${sortExpression}' What it means
visitSortSpecification calls visitSortExpression and throws SemanticException when it returns null, i.e. the order-by expression could not be converted into any SqmExpression. This happens for order-by items that are neither resolvable expressions nor usable positional/alias references - notably bare identifiers used where positional/alias references are disallowed (inside 'over(...)' or 'within group' clauses, where allowPositionalOrAliases is false) and that also fail to resolve as paths.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java:1798
orderByClause.addSortSpecification( visitSortSpecification(
sortSpecificationContexts.get( i ),
allowPositionalOrAliases
) );
}
return orderByClause;
}
@Override
public SqmSortSpecification visitSortSpecification(HqlParser.SortSpecificationContext ctx) {
return visitSortSpecification( ctx, true );
}
private SqmSortSpecification visitSortSpecification(
HqlParser.SortSpecificationContext ctx,
boolean allowPositionalOrAliases) {
final var sortExpression = visitSortExpression( ctx.sortExpression(), allowPositionalOrAliases );
if ( sortExpression == null ) {
throw new SemanticException( "Could not resolve sort expression: '" + ctx.sortExpression().getText() + "'",
query );
}
if ( sortExpression instanceof SqmLiteral || sortExpression instanceof SqmParameter ) {
HqlLogging.QUERY_LOGGER.debugf( "Questionable sorting by constant value: %s", sortExpression );
}
return new SqmSortSpecification( sortExpression, sortOrder( ctx ), nullPrecedence( ctx ) );
}
private static SortDirection sortOrder(HqlParser.SortSpecificationContext ctx) {
return ctx.sortDirection() == null || ctx.sortDirection().DESC() == null
? SortDirection.ASCENDING
: SortDirection.DESCENDING;
}
private static Nulls nullPrecedence(HqlParser.SortSpecificationContext ctx) {
if ( ctx.nullsPrecedence() == null ) {
return Nulls.NONE;
}View on GitHub (pinned to fad1729dce)
Solutions
- Inside over()/within group, repeat the underlying expression: 'over (order by e.name)'
- Verify the alias spelling against the select list
- Order by the actual attribute path instead of an alias
Example fix
// before select e.name as n, rank() over (order by n) from Employee e // after select e.name as n, rank() over (order by e.name) from Employee e
Defensive patterns
Strategy: validation
Validate before calling
// Reject select aliases used inside over()/within group before execution
static boolean aliasInsideWindow(String hql, Set<String> selectAliases) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile("\\bover\\s*\\(([^)]*)\\)", java.util.regex.Pattern.CASE_INSENSITIVE).matcher(hql);
while (m.find()) {
String window = m.group(1).toLowerCase();
for (String a : selectAliases) {
if (java.util.regex.Pattern.compile("\\b" + java.util.regex.Pattern.quote(a.toLowerCase()) + "\\b").matcher(window).find()) return true;
}
}
return false;
} Try / catch
try {
return em.createQuery(hql, Object[].class).getResultList();
} catch (org.hibernate.query.sqm.SemanticException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Could not resolve sort expression")) {
throw new IllegalArgumentException("Unresolvable order-by item - spell out the expression instead of an alias: " + hql, e);
}
throw e;
} Prevention
- Never use select-list aliases inside over(...) or within group clauses - repeat the expression
- Double-check alias spelling in order by against the select list
- Add integration tests that translate every stored query (createQuery) so failures surface at build time
When it happens
Trigger: 'select e.name as n, rank() over (order by n) from Employee e' (select alias inside a window ORDER BY); ordering by an identifier that is neither a select alias, a from alias, nor a resolvable attribute path.
Common situations: Using SQL-style select aliases inside window functions (accepted by several databases, rejected by HQL); alias typos; migrating JPQL between providers with different alias-scoping rules.
Related errors
- Can't emulate [%s] in clause %s. Only the SELECT clause is s
- Can't emulate [%s] in clause %s. Only the SELECT clause is s
- The function {name} is not a window function
- Insert conflict 'do update' clause with constraint name is n
- field type not supported on Derby: " + unit
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7778eaadc90a2bea.
Report an issue: GitHub.