hibernate/hibernate-orm · error · IllegalQueryOperationException
Insert conflict 'do update' clause with constraint name is n
Error message
Insert conflict 'do update' clause with constraint name is not supported
What it means
Hibernate 6.6+ HQL upserts use 'insert ... on conflict do update', optionally with a named constraint target ('on conflict on constraint <name>'). H2LegacySqlAstTranslator.visitConflictClause throws IllegalQueryOperationException for that named-constraint form because the H2 conflict rendering cannot bind the upsert to a specific constraint name.
Source
Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacySqlAstTranslator.java:179
}
else {
super.visitUpdateStatementOnly( statement );
}
}
@Override
protected void renderDmlTargetTableExpression(NamedTableReference tableReference) {
super.renderDmlTargetTableExpression( tableReference );
if ( getClauseStack().getCurrent() != Clause.INSERT ) {
renderTableReferenceIdentificationVariable( tableReference );
}
}
@Override
protected void visitConflictClause(ConflictClause conflictClause) {
if ( conflictClause != null ) {
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
}
}
}
@Override
public void visitCteContainer(CteContainer cteContainer) {
// H2 has various bugs in different versions that make it impossible to use CTEs with parameters reliably
withParameterRenderingMode(
SqlAstNodeRenderingMode.INLINE_PARAMETERS,
() -> super.visitCteContainer( cteContainer )
);
}
@Override
protected boolean needsCteInlining() {
// CTEs in H2 are just so buggy, that we can't reliably use them
return true;
}View on GitHub (pinned to fad1729dce)
Solutions
- Remove the constraint name: 'on conflict do update set ...' - Hibernate infers the conflict target from the unique key
- If disambiguation is needed, use the column-list target 'on conflict (col1, col2) do update'
- Move the statement to a native H2 MERGE ... KEY query
- Migrate the test database off the legacy dialect (H2 2.x with the current H2Dialect), which renders conflict clauses natively
Example fix
// before (HQL, throws on H2 legacy dialect) insert into Person (id, name) select p.id, p.name from StagePerson p on conflict on constraint uk_person_id do update set name = excluded.name // after (target-less conflict clause) insert into Person (id, name) select p.id, p.name from StagePerson p on conflict do update set name = excluded.name
Defensive patterns
Strategy: validation
Validate before calling
Dialect d = sessionFactory.getJdbcServices().getDialect();
if (d instanceof org.hibernate.community.dialect.H2LegacyDialect && hql.contains("on conflict on constraint")) {
hql = hql.replaceFirst("on constraint \\w+", "");
} Type guard
static boolean namedConflictTargetSafe(Dialect d) {
return !(d instanceof org.hibernate.community.dialect.H2LegacyDialect);
} Try / catch
try {
q = session.createQuery(hql);
} catch (org.hibernate.query.IllegalQueryOperationException e) {
if (e.getMessage().contains("constraint name")) {
q = session.createQuery(hql.replaceFirst("on constraint \\w+", ""));
} else throw e;
} Prevention
- Write upserts without a named constraint target unless a specific dialect requires it
- Prefer the column-list target 'on conflict (cols)' over 'on constraint <name>' for portability
- Upgrade test H2 databases off the legacy dialect to exercise modern conflict-clause rendering
When it happens
Trigger: An HQL insert with 'on conflict on constraint <constraintName> do update set ...' running under the H2 legacy dialect (H2LegacyDialect / H2LegacySqlAstTranslator). The target-less form and the column-list target 'on conflict (cols) do update' do not hit this throw.
Common situations: H2 test databases pinned to the legacy dialect after a Hibernate upgrade; test fixtures copied from PostgreSQL production queries that name constraints; multi-database test matrices where only the H2-legacy member fails.
Related errors
- Insert conflict 'do update' clause with constraint name is n
- Insert conflict 'do update' clause with constraint name is n
- Summarization is not supported by DBMS
- Insert conflict 'do update' clause with constraint name is n
- Insert conflict 'do update' clause with constraint name is n
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/0d7c6b6eeae5adfe.
Report an issue: GitHub.