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.
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
- Select item at position
- A CTE with the label
- Could not determine ValueMapping for SqmExpression
- CTE joins can not be treated
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/906ba8b7cbfe4bdc.
Report an issue: GitHub.
Appendix: 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)