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

  1. Alias every select item in every CTE and from-clause subquery: `select e.id as id, e.name as name from Entity e`.
  2. Check compound selections too - every leaf selectable node needs an alias, not just the outer expression.
  3. 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

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


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