hibernate/hibernate-orm · error · InterpretationException
Could not find CTE for name '" + cteName + "'!
Error message
Could not find CTE for name '" + cteName + "'!
What it means
Thrown when createCteTableGroup() builds the table group for a reference to a CTE and cteContainer.getCteStatement(cteName) returns null. The statement being translated refers to a CTE label that is registered neither in the current CTE scope nor in any parent scope, so there is no definition to read the table group producer from.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java:3214
inNestedContext = oldInNestedContext;
if ( !lateral ) {
fromClauseIndexStack.pop();
}
}
}
private TableGroup createCteTableGroup(
String cteName,
NavigablePath navigablePath,
String explicitAlias,
boolean canUseInnerJoins) {
final var sqlAliasBase = getSqlAliasBaseGenerator().createSqlAliasBase(
explicitAlias == null ? cteName : explicitAlias
);
final String identifierVariable = sqlAliasBase.generateNewAlias();
final var cteStatement = cteContainer.getCteStatement( cteName );
if ( cteStatement == null ) {
throw new InterpretationException( "Could not find CTE for name '" + cteName + "'!" );
}
final var cteQueryPart = ( (SelectStatement) cteStatement.getCteDefinition() ).getQueryPart();
// If the query part of the CTE is one which we are currently processing, then this is a recursive CTE
if ( cteQueryPart instanceof QueryGroup && TRUE == processingStateStack.findCurrentFirstWithParameter( cteQueryPart, BaseSqmToSqlAstConverter::matchSqlAstWithQueryPart ) ) {
cteStatement.setRecursive();
}
final var tableGroupProducer = cteStatement.getCteTable().getTableGroupProducer();
return new CteTableGroup(
canUseInnerJoins,
navigablePath,
sqlAliasBase,
tableGroupProducer,
new NamedTableReference( cteName, identifierVariable ),
tableGroupProducer.getCompatibleTableExpressions()
);
}
private void consumeJoins(SqmRoot<?> sqmRoot, FromClauseIndex fromClauseIndex, TableGroup tableGroup) {View on GitHub (pinned to fad1729dce)
Solutions
- Make the referenced name exactly match the with-clause label, including case and any backtick quoting
- Declare the CTE at the statement level that actually references it, not inside a deeper subquery
- If building the query programmatically, add the CteStatement to the SqmCteContainer before any reference is translated
- Verify the dialect supports CTEs at all; unsupported dialects can drop statements from the container
Example fix
// before with totals as (select p.id, sum(o.amt) t from ...) select * from total s // after with totals as (select p.id, sum(o.amt) t from ...) select * from totals
Defensive patterns
Strategy: try-catch
Validate before calling
// For programmatically built queries: verify each referenced CTE is declared in scope
Set<String> declared = cteContainer.getCteStatements().stream()
.map(s -> s.getCteTable().getCteName())
.collect(java.util.stream.Collectors.toSet());
if (!declared.contains(referenceName)) {
throw new IllegalStateException("CTE '" + referenceName + "' referenced but not declared: " + declared);
} Try / catch
try {
return session.createQuery(hql).getResultList();
} catch (org.hibernate.query.sqm.InterpretationException e) {
log.error("CTE reference failed; with-clause labels in query: {}", extractWithLabels(hql), e);
throw e;
} Prevention
- Define CTE label constants and use them in both the with-clause and from-clause
- Declare CTEs at the top statement level, never inside a subquery that others reference
- Unit-test every HQL with a with-clause against a real SessionFactory in CI
When it happens
Trigger: HQL 'with x as (...) select ... from y' where the from-clause name y is a typo for x; referencing a CTE that is declared inside a nested subquery from the outer statement (out of scope); case or quoting mismatches between the with-clause label and the reference (backticked vs plain name).
Common situations: Hand-written HQL with with-clauses where label and usage drift apart; refactoring that renames a CTE in the with-clause but not in the from-clause; queries assembled from string fragments; criteria code that consumes a CTE before adding its statement to the container.
Related errors
- Couldn't generate CTE name for base name [%s] after %d tries
- Select item at position ${i+1} in select list has no alias (
- 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/906ba8b7cbfe4bdc.
Report an issue: GitHub.