hibernate/hibernate-orm · error · IllegalArgumentException
A CTE object with the name {} already exists
Error message
A CTE object with the name {} already exists What it means
The CteObject counterpart of the duplicate-label check: addCteObject registers CTE objects (Hibernate 7's modifiable/mutation CTE objects) by name with putIfAbsent and throws IllegalArgumentException if an object with the same name is already registered in the same CTE scope.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java:9516
}
@Override
public Map<String, CteObject> getCteObjects() {
return cteObjects;
}
@Override
public CteObject getCteObject(String cteObjectName) {
final var cteObject = cteObjects.get( cteObjectName );
return cteObject == null && parent != null
? parent.getCteObject( cteObjectName )
: cteObject;
}
@Override
public void addCteObject(CteObject cteObject) {
if ( cteObjects.putIfAbsent( cteObject.getName(), cteObject ) != null ) {
throw new IllegalArgumentException( "A CTE object with the name " + cteObject.getName() + " already exists" );
}
}
}
@Override
public boolean registerVisitedAssociationKey(AssociationKey associationKey) {
return visitedAssociationKeys.add( associationKey );
}
@Override
public void removeVisitedAssociationKey(AssociationKey associationKey) {
visitedAssociationKeys.remove( associationKey );
}
@Override
public boolean isAssociationKeyVisited(AssociationKey associationKey) {
return visitedAssociationKeys.contains( associationKey );
}View on GitHub (pinned to fad1729dce)
Solutions
- Give each CTE object a unique name within the statement
- When composing statements from fragments, prefix object names with a scope or counter
- Reuse the existing CteObject instead of registering a second one under the same name
Example fix
// before
container.addCteObject(new CteObject("changes", ...));
container.addCteObject(new CteObject("changes", ...));
// after
container.addCteObject(new CteObject("changes_1", ...));
container.addCteObject(new CteObject("changes_2", ...)); Defensive patterns
Strategy: validation
Validate before calling
Set<String> names = container.getCteObjects().keySet();
if (names.contains(cteObject.getName())) {
throw new IllegalArgumentException("CTE object '" + cteObject.getName() + "' already exists");
}
container.addCteObject(cteObject); Try / catch
try {
session.createQuery(hql).executeUpdate();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("CTE object")) {
log.error("Duplicate CTE object name in: {}", hql);
}
throw e;
} Prevention
- Namespace CTE object names per statement fragment
- Register each CTE object exactly once per scope
- Unit-test statement composition for name collisions
When it happens
Trigger: Programmatically registering two CteObject instances with the same name on one statement; HQL or criteria using the new modifiable-CTE feature ('with ... update/delete ... returning') twice under one name; merging containers that both carry a same-named CTE object.
Common situations: Adopting Hibernate 7 CTE objects for insert/update returning-style flows; name templates that collide when a statement is composed from repeated fragments.
Related errors
- A CTE with the label {} already exists
- A CTE with the label {} already exists
- Index {} already exists
- UniqueKey {} already exists
- Different CTE with same name [%s] found in different set ope
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/66ed45ff8e3c9238.
Report an issue: GitHub.