{"record":{"id":"399c72af818cb418","repo":"hibernate/hibernate-orm","slug":"couldn-t-generate-cte-name-for-base-name-s-afte","errorCode":null,"errorMessage":"Couldn't generate CTE name for base name [%s] after %d tries","messagePattern":"Couldn't generate CTE name for base name \\[(.+?)\\] after (.+?) tries","errorType":"exception","errorClass":"InterpretationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java","lineNumber":1888,"sourceCode":"\t\t\t// route the CTE name through the IdentifierHelper so it gets the same quoting\n\t\t\t// treatment (reserved words, global/auto quoting) as any other identifier\n\t\t\tfinal String cteName = getSessionFactory().getJdbcServices().getJdbcEnvironment()\n\t\t\t\t\t.getIdentifierHelper().toIdentifier( generatedName ).render( getDialect() );\n\t\t\tcteNameMapping.put( key, cteName );\n\t\t\treturn cteName;\n\t\t}\n\t}\n\n\tprivate String generateCteName(String baseName) {\n\t\tString name = baseName;\n\t\tint maxTries = 5;\n\t\tfor ( int i = 0; i < maxTries; i++ ) {\n\t\t\tif ( !cteNameMapping.containsKey( name ) ) {\n\t\t\t\treturn name;\n\t\t\t}\n\t\t\tname = baseName + \"_\" + i;\n\t\t}\n\t\tthrow new InterpretationException(\n\t\t\t\tString.format(\n\t\t\t\t\t\t\"Couldn't generate CTE name for base name [%s] after %d tries\",\n\t\t\t\t\t\tbaseName,\n\t\t\t\t\t\tmaxTries\n\t\t\t\t)\n\t\t);\n\t}\n\n\tprivate Literal getLiteral(SqmLiteral<?> value) {\n\t\treturn value == null ? null : (Literal) visitLiteral( value );\n\t}\n\n\tprotected List<SearchClauseSpecification> visitSearchBySpecifications(\n\t\t\tCteTable cteTable,\n\t\t\tList<JpaSearchOrder> searchBySpecifications) {\n\t\tif ( searchBySpecifications == null || searchBySpecifications.isEmpty() ) {\n\t\t\treturn null;\n\t\t}","sourceCodeStart":1870,"sourceCodeEnd":1906,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java#L1870-L1906","documentation":"Thrown during SQM-to-SQL translation when Hibernate must invent a SQL-level name for a CTE and every candidate collides. getCteName() derives a base name from the SqmCteTable label (or a synthetic 'cte<n>'), and generateCteName() tries baseName, then baseName_0 through baseName_3 (5 tries) against cteNameMapping; if all 5 are taken, translation aborts with an InterpretationException.","triggerScenarios":"A single HQL statement that registers six or more CTEs whose labels collapse to the same generated base name: many subqueries or union branches re-declaring the same CTE label, a criteria query with JpaCteCriteria added repeatedly under one name, or programmatically generated with-clauses where SqmCteTables carry no explicit name and their fallback names collide after identifier rendering.","commonSituations":"Programmatically built queries (criteria + CTE containers) in reporting/data-pipeline code; heavy use of union all with shared CTE labels; upgrades between Hibernate versions where CTE name generation changed; test suites generating very wide with-clauses.","solutions":["Give every CTE in the statement a unique explicit label instead of relying on generated names","Reduce the number of CTEs: merge equivalent CTEs or inline the ones used only once","Split the statement into multiple sequential queries so each statement registers fewer CTEs","If labels are already unique and it still fails, file a Hibernate JIRA with the query - a genuinely unique base name should never exhaust 5 tries"],"exampleFix":"// before (criteria, same label reused across many branches)\ncteContainer.with(\"data\", dataQuery);\n...\n// after: unique labels per CTE\ncteContainer.with(\"data_\" + branchIndex, dataQuery);","handlingStrategy":"try-catch","validationCode":"// Before executing, sanity-check that CTE labels in one statement are unique\n// (HQL): count labels in the with-clause\njava.util.List<String> labels = java.util.Arrays.stream(hql.split(\"\\\\s+\"))\n    .filter(w -> w.equalsIgnoreCase(\"with\") || w.contains(\",\")) .count() > 5\n        ? java.util.Collections.singletonList(\"review-cte-count\")\n        : java.util.Collections.emptyList();","typeGuard":null,"tryCatchPattern":"try {\n    Query<?> q = session.createQuery(hql);\n    return q.getResultList();\n} catch (org.hibernate.query.sqm.InterpretationException e) {\n    log.error(\"Query failed to translate: {}\", hql, e);\n    throw new QueryTranslationFailure(hql, e); // keep the HQL with the error for diagnosis\n}","preventionTips":["Always pass explicit, unique labels when adding CTEs programmatically","Keep with-clauses small: inline single-use CTEs instead of declaring them","Log the generated HQL/SQM for dynamically built queries so collisions are diagnosable"],"tags":["hibernate","hql","cte","query-translation","name-collision"],"backgroundTag":"cte-name-collision","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}