hibernate/hibernate-orm · error · HibernateException
Duplicate identifier in table (%s) - %s#%s
Error message
Duplicate identifier in table (%s) - %s#%s
What it means
A mutation against an identified table reported more affected rows than the expectation permits (TooManyRowsAffectedException caught in Checkers.identifiedResultsCheck). Because the statement targets rows by primary key, more than one affected row means the table physically contains duplicate rows for the same identifier - a data-integrity violation surfaced as 'Duplicate identifier in table (... - entity#id)'.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/action/queue/spi/bind/Checkers.java:53
expectation.verifyOutcome(
affectedRowCount,
null,
batchPosition,
sqlString
);
}
catch (StaleStateException e) {
if ( !mutatingTable.isOptional() && affectedRowCount == 0 ) {
final StatisticsImplementor statistics = sessionFactory.getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.optimisticFailure( mutationTarget.getNavigableRole().getFullPath() );
}
throw new StaleObjectStateException( mutationTarget.getNavigableRole().getFullPath(), id, e );
}
return false;
}
catch (TooManyRowsAffectedException e) {
throw new HibernateException(
String.format(
Locale.ROOT,
"Duplicate identifier in table (%s) - %s#%s",
mutatingTable.name(),
mutationTarget.getNavigableRole().getFullPath(),
id
)
);
}
catch (Throwable t) {
return false;
}
return true;
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Locate duplicates with SELECT id, COUNT(*) FROM <table> GROUP BY id HAVING COUNT(*) > 1, delete the extras, then re-add the primary key constraint.
- On SQL Server, ensure triggers on the table issue SET NOCOUNT ON so the true affected count reaches the driver.
- Verify the mutation target's join/key column mapping matches the actual schema - a wrong column can match multiple rows.
Example fix
-- before: no PK enforced, duplicates exist SELECT order_id, COUNT(*) FROM order_lines GROUP BY order_id HAVING COUNT(*) > 1; -- fix data, then enforce the key DELETE FROM order_lines WHERE ctid NOT IN (SELECT MIN(ctid) FROM order_lines GROUP BY order_id); ALTER TABLE order_lines ADD PRIMARY KEY (order_id);
Defensive patterns
Strategy: validation
Validate before calling
// health check: detect duplicate ids before Hibernate does
List<Object[]> dupes = em.createNativeQuery(
"select id, count(*) from order_lines group by id having count(*) > 1")
.getResultList();
if (!dupes.isEmpty()) throw new IllegalStateException("duplicate rows: " + dupes); Try / catch
try {
session.flush();
}
catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Duplicate identifier in table")) {
// quarantine and repair the duplicated rows, then retry the transaction
}
else throw e;
} Prevention
- Always enforce primary key constraints on mutation tables, including secondary/joined tables
- Set SET NOCOUNT ON in SQL Server triggers so affected-row counts stay accurate
- Validate bulk imports for id uniqueness before they reach production tables
When it happens
Trigger: UPDATE/DELETE ... WHERE id = ? affecting 2+ rows: duplicate PK rows in the table because the primary key constraint is missing or was dropped; or a SQL Server trigger altering the reported affected-row count.
Common situations: Joined-inheritance/secondary tables populated by hand or by a buggy migration without PK enforcement; SQL Server triggers missing SET NOCOUNT ON so the driver double-counts; imports that duplicated rows.
Related errors
- Duplicate identifier in table (%s) - %s#%s
- assigned tenant id differs from current tenant id [{} != {}]
- Cannot update previous revision for entity %s and id %s (%s
- Retrieved key was null, but to-one is not nullable : %s
- Illegal null value for array index encountered while reading
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7ea8cbcc311d5426.
Report an issue: GitHub.