hibernate/hibernate-orm · error · SemanticException
Select item at position ${i+1} in select list has no alias (
Error message
Select item at position ${i+1} in select list has no alias (aliases are required in CTEs and in subqueries occurring in from clause) What it means
When Hibernate 6 derives the tuple type of a CTE or a from-clause subquery, each selection must carry an alias because the tuple's components are named and looked up by alias (componentIndexMap). A select item without an alias makes the AnonymousTupleType constructor throw SemanticException('Select item at position N ... has no alias') during query compilation.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleType.java:102
// for compound selections we use the sub-selectable nodes aliases
aliases.add( selection.getAlias() );
}
}
expressibles = new SqmBindableType<?>[selectableNodes.size()];
componentSourcePaths = new NavigablePath[selectableNodes.size()];
componentNames = new String[selectableNodes.size()];
//noinspection unchecked
javaTypeDescriptor = (JavaType<T>) new ObjectArrayJavaType( getTypeDescriptors( selectableNodes ) );
componentIndexMap = linkedMapOfSize( selectableNodes.size() );
for ( int i = 0; i < selectableNodes.size(); i++ ) {
expressibles[i] = selectableNodes.get( i ).getNodeType();
if ( selectableNodes.get( i ) instanceof SqmPath<?> path ) {
componentSourcePaths[i] = path.getNavigablePath();
}
String alias = aliases.get( i );
if ( alias == null ) {
throw new SemanticException( "Select item at position " + (i+1) + " in select list has no alias"
+ " (aliases are required in CTEs and in subqueries occurring in from clause)" );
}
componentIndexMap.put( alias, i );
componentNames[i] = alias;
}
}
public AnonymousTupleType(SqmBindableType<?>[] expressibles, String[] componentNames) {
this.expressibles = expressibles;
this.componentNames = componentNames;
componentSourcePaths = new NavigablePath[componentNames.length];
componentIndexMap = linkedMapOfSize( expressibles.length );
int elementIndex = -1;
for ( int i = 0; i < componentNames.length; i++ ) {
if ( CollectionPart.Nature.ELEMENT.getName().equals( componentNames[i] ) ) {
elementIndex = i;
}View on GitHub (pinned to fad1729dce)
Solutions
- Alias every select item in every CTE and from-clause subquery: `select e.id as id, e.name as name from Entity e`.
- Check compound selections too - every leaf selectable node needs an alias, not just the outer expression.
- Add a startup/unit test that compiles all CTE queries so missing aliases fail in CI, not production.
Example fix
// before "with recent as (select o.id, o.date from Orders o where o.date > :d) select r.id from recent r" // -> SemanticException: Select item at position 1 in select list has no alias // after "with recent as (select o.id as id, o.date as date from Orders o where o.date > :d) select r.id from recent r"
Defensive patterns
Strategy: validation
Validate before calling
// validate generated HQL CTEs before execution: every select item needs an alias
static String requireCteAliases(String hql) {
// for each CTE body, ensure select items contain " as alias"
// simplest guard: reject 'with ... as (select <expr>,' patterns lacking 'as'
if (CTE_ALIAS_PATTERN.matcher(hql).find()) {
throw new IllegalArgumentException("CTE select item without alias: " + hql);
}
return hql;
} Try / catch
try {
return session.createQuery(hql).getResultList();
} catch (SemanticException e) {
// missing alias in CTE/from-subquery select list; message names the position
throw new QueryBuildException("Alias missing in CTE select list: " + e.getMessage(), e);
} Prevention
- Alias every select item in CTEs and from-clause subqueries by convention (id as id, ...).
- Add a lint rule or code review checklist item for generated HQL aliases.
- Compile all CTE queries in CI so missing aliases fail before production.
When it happens
Trigger: HQL like `with cte as (select e.id, e.name from Entity e) select ... from cte` - the items e.id and e.name have no `as id` / `as name` aliases; same for from-clause subqueries used as tuple sources.
Common situations: Porting native SQL CTEs into HQL; migrating Hibernate 5.x applications where these query shapes were written without aliases; dynamically generated HQL that forgets aliases for some items (including compound selections like counts or case expressions).
Related errors
- Couldn't generate CTE name for base name [%s] after %d tries
- Could not find CTE for name '" + cteName + "'!
- Insert conflict 'do update' clause with constraint name is n
- Summarization is not supported by DBMS
- Insert conflict 'do update' clause with constraint name is n
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f6c91f580884522d.
Report an issue: GitHub.