{"record":{"id":"6e765d749568d1a9","repo":"hibernate/hibernate-orm","slug":"a-cte-with-the-label-already-exists-6e765d","errorCode":null,"errorMessage":"A CTE with the label {} already exists","messagePattern":"A CTE with the label (.+?) already exists","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/AbstractSqmDmlStatement.java","lineNumber":75,"sourceCode":"\t\tsuper( builder, querySource, parameters );\n\t\tthis.cteStatements = cteStatements;\n\t\tthis.target = target;\n\t}\n\n\tprotected Map<String, SqmCteStatement<?>> copyCteStatements(SqmCopyContext context) {\n\t\tfinal Map<String, SqmCteStatement<?>> copy =\n\t\t\t\tnew LinkedHashMap<>( cteStatements.size() );\n\t\tfor ( var entry : cteStatements.entrySet() ) {\n\t\t\tcopy.put( entry.getKey(), entry.getValue().copy( context ) );\n\t\t}\n\t\treturn copy;\n\t}\n\n\tprotected void putAllCtes(SqmCteContainer cteContainer) {\n\t\tfor ( var cteStatement : cteContainer.getCteStatements() ) {\n\t\t\tfinal String cteName = cteStatement.getCteTable().getCteName();\n\t\t\tif ( cteStatements.putIfAbsent( cteName, cteStatement ) != null ) {\n\t\t\t\tthrow new IllegalArgumentException( \"A CTE with the label \" + cteName + \" already exists\" );\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic abstract void validate(@Nullable String hql);\n\n\t@Override\n\t@Nonnull\n\tpublic Collection<SqmCteStatement<?>> getCteStatements() {\n\t\treturn cteStatements.values();\n\t}\n\n\t@Override\n\t@Nullable public SqmCteStatement<?> getCteStatement(String cteLabel) {\n\t\treturn cteStatements.get( cteLabel );\n\t}\n\n\t@Override","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/AbstractSqmDmlStatement.java#L57-L93","documentation":"AbstractSqmDmlStatement.putAllCtes merges the CTE statements of another SqmCteContainer into a DML statement's own with-clause, keyed by CTE name. A putIfAbsent hit means the incoming container declares a CTE label the DML statement already has, which throws IllegalArgumentException.","triggerScenarios":"An HQL DML statement with a with-clause whose label also appears in the source/subquery container it absorbs - e.g. 'insert into ... with t as (...) select ... from t' during copy/merge operations; criteria DML (SqmInsertSelectStatement etc.) whose target and source query both define the same CTE name.","commonSituations":"Building insert-select or update-with-CTE statements programmatically where both halves share boilerplate CTE names; reusing a prepared select query (with its CTEs) as the source of an insert; upgrades that changed how DML statements merge CTE containers.","solutions":["Rename the duplicate CTE in either the DML statement's with-clause or the absorbed source query","Build the source select query without its own with-clause if the outer DML already declares the CTE","When copying DML criteria, clear or namespace CTE names before merging containers"],"exampleFix":"// before\ninsert into T (a) with src as (select ...) select x from src\n// where the source select statement also declares src\n\n// after: unique labels\ninsert into T (a) with src_outer as (select ...) select x from src_outer","handlingStrategy":"validation","validationCode":"// Before putAll-style merge: verify no label overlap\nSet<String> mine = dmlStatement.getCteStatements().stream()\n    .map(s -> s.getCteTable().getCteName()).collect(java.util.stream.Collectors.toSet());\nboolean clash = sourceContainer.getCteStatements().stream()\n    .map(s -> s.getCteTable().getCteName()).anyMatch(mine::contains);\nif (clash) {\n    throw new IllegalArgumentException(\"Refusing to merge CTEs: duplicate label between DML and source query\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    session.createQuery(hqlDml).executeUpdate();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"A CTE with the label\")) {\n        log.error(\"Duplicate CTE label in DML: {}\", hqlDml);\n    }\n    throw e;\n}","preventionTips":["When reusing a select query as the source of insert-select, strip or rename its with-clause","Keep one naming authority for CTE labels per statement assembly","Test DML-with-CTE statements end to end in CI"],"tags":["hibernate","cte","dml","duplicate-name","insert-select"],"backgroundTag":"duplicate-cte-name","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}