hibernate/hibernate-orm · error · HibernateException
Duplicate identifier in table (%s) - %s#%s
Error message
Duplicate identifier in table (%s) - %s#%s
What it means
When a single insert/update/delete reports more affected rows than expected (TooManyRowsAffectedException), ModelMutationHelper wraps it as HibernateException 'Duplicate identifier in table (T) - Role#id': the database updated/deleted several rows for one identifier, which by Hibernate's mapping should be impossible for a correctly-keyed table.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/mutation/internal/ModelMutationHelper.java:77
statementDetails.getStatement(),
batchPosition,
statementDetails.getSqlString()
);
return true;
}
catch (StaleStateException e) {
if ( !statementDetails.getMutatingTableDetails().isOptional() && affectedRowCount == 0 ) {
final String fullPath = mutationTarget.getNavigableRole().getFullPath();
final var statistics = sessionFactory.getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.optimisticFailure( fullPath );
}
throw new StaleObjectStateException( fullPath, id, e );
}
return false;
}
catch (TooManyRowsAffectedException e) {
throw new HibernateException(
String.format(
Locale.ROOT,
"Duplicate identifier in table (%s) - %s#%s",
statementDetails.getMutatingTableDetails().getTableName(),
mutationTarget.getNavigableRole().getFullPath(),
id
)
);
}
catch (Throwable t) {
return false;
}
}
public static PreparedStatementGroup toPreparedStatementGroup(
MutationType mutationType,
MutationTarget<?,?> mutationTarget,
GeneratedValuesMutationDelegate delegate,View on GitHub (pinned to fad1729dce)
Solutions
- Find the duplicates: SELECT id, COUNT(*) FROM <table> GROUP BY id HAVING COUNT(*) > 1, then repair/delete the extra rows
- Restore the primary key / unique constraints on the affected table so duplicates cannot recur
- Verify the entity mapping is not accidentally mapping two entities to the same table row space (shared tables, @Tables/@Table annotations)
Example fix
-- diagnosis SELECT id, COUNT(*) FROM child_table GROUP BY id HAVING COUNT(*) > 1; -- repair DELETE FROM child_table WHERE rowid NOT IN (SELECT MIN(rowid) FROM child_table GROUP BY id); ALTER TABLE child_table ADD PRIMARY KEY (id);
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight duplicate check on id columns used by Hibernate SELECT id, COUNT(*) FROM child_table GROUP BY id HAVING COUNT(*) > 1; -- add PK constraints so the invariant cannot regress ALTER TABLE child_table ADD CONSTRAINT pk_child PRIMARY KEY (id);
Try / catch
try {
session.merge(entity);
session.flush();
}
catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Duplicate identifier in table")) {
// run the duplicate-detection query and page an on-call data fix
}
} Prevention
- Always enforce PK/unique constraints on secondary and inheritance tables
- Validate bulk-imported data for duplicate ids before it reaches the app
- Audit any manual DDL that dropped constraints
When it happens
Trigger: The mutated table physically contains multiple rows with the same primary key value — typically secondary tables or JOINED-inheritance child tables whose PK/FK constraint is missing or was dropped — or data was bulk-imported/merged creating duplicates, so an UPDATE ... WHERE id = ? hits several rows.
Common situations: Bulk loads into inheritance tables without enforced primary keys; constraints dropped 'temporarily' in prod and never restored; manual data fixes that inserted duplicate child rows; database restores that duplicated rows.
Related errors
- Duplicate identifier in table (%s) - %s#%s
- Expected object of type `%s`, but found `%s`; discriminator
- Entity `%s` with identifier value `%s` does not exist
- Root entity '<entityName>' is annotated '@DiscriminatorOptio
- Class '<className>' is not the root class of an entity inher
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7d4998d0a4353b7c.
Report an issue: GitHub.