hibernate/hibernate-orm · error · IllegalStateException

Could not determine a path column name after 5 tries!

Error message

Could not determine a path column name after 5 tries!

What it means

When emulating a CYCLE clause on a dialect without native 'cycle ... using' support, determineCyclePathColumnName must invent the column that stores the visited-path array. If the query did not name it explicitly (no USING path_col), it tries 'path', 'path_1' .. 'path_4', skipping names taken by CTE columns, the search column, or the cycle mark column. Exhausting all five candidates throws IllegalStateException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:2477

		OUTER: for ( int tries = 0; tries < 5; tries++ ) {
			final String name = tries == 0 ? baseName : (baseName + "_" + tries);
			for ( CteColumn cteColumn : cte.getCteTable().getCteColumns() ) {
				if ( name.equals( cteColumn.getColumnExpression() ) ) {
					continue OUTER;
				}
			}
			if ( cte.getSearchColumn() != null
					&& name.equals( cte.getSearchColumn().getColumnExpression() ) ) {
				continue;
			}
			if ( cte.getCycleMarkColumn() != null
					&& name.equals( cte.getCycleMarkColumn().getColumnExpression() ) ) {
				continue;
			}

			return name;
		}
		throw new IllegalStateException( "Could not determine a path column name after 5 tries!" );
	}

	protected boolean isInRecursiveQueryPart() {
		return currentCteStatement != null
			&& currentCteStatement.isRecursive()
			&& ( (QueryGroup) ( (SelectStatement) currentCteStatement.getCteDefinition() ).getQueryPart() )
					.getQueryParts().get( 1 ) == getCurrentQueryPart();
	}

	protected boolean isInSubquery() {
		return statementStack.depth() > 1
			&& statementStack.getCurrent() instanceof SelectStatement selectStatement
			&& !selectStatement.getQueryPart().isRoot();
	}

	protected void visitCteDefinition(CteStatement cte) {
		final CteStatement oldCteStatement = currentCteStatement;
		currentCteStatement = cte;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Name the cycle path column explicitly with the USING clause ('cycle ... set ... default ... using visit_path') so no name has to be invented.
  2. Rename the CTE's own columns so at least one of path, path_1..path_4 stays free.
  3. Handle cycle protection manually with a NOT EXISTS/anti-join predicate in the recursive part instead of the CYCLE clause.
  4. Use a native query if the schema column names cannot be changed.

Example fix

-- before: CYCLE clause with implicit path name and all candidates taken
with recursive t(id, path, path_1, path_2, path_3, path_4) as (...) cycle id set is_cycle to true default false select * from t
-- after: explicit USING column name
cycle id set is_cycle to true default false using visit_path
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at least one emulated path name is free, or name the path column explicitly
java.util.Set<String> reserved = java.util.Set.of("path", "path_1", "path_2", "path_3", "path_4");
if ( cteColumnNames.containsAll(reserved) && !dialect.supportsRecursiveCycleClause() ) {
    throw new IllegalStateException("Rename CTE columns or add an explicit USING path column");
}

Try / catch

try {
    return session.createQuery(graphHql, ResultDto.class).getResultList();
} catch (IllegalStateException e) {
    if ( e.getMessage() != null && e.getMessage().contains("path column name") ) {
        throw new IllegalStateException("CTE columns path..path_4 collide with the emulated cycle path column; add 'using <name>' to the CYCLE clause", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A recursive CTE with a CYCLE clause lacking an explicit path column (HQL 'cycle col set mark to true default false' without 'using <path_col>'), on a dialect where supportsRecursiveCycleClause()/supportsRecursiveCycleUsingClause() is false, whose CTE columns already occupy all of path, path_1, path_2, path_3, path_4 (or those collide with search/cycle mark columns).

Common situations: Graph-traversal CTEs that already project materialized path columns (path, path_1, ... for alternate routes); tree structures where 'path' is a natural business column name; migrations that added path_N columns for history tracking.

Related errors


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