hibernate/hibernate-orm · error · HibernateException
Duplicate row was found and `%s` was specified
Error message
Duplicate row was found and `%s` was specified
What it means
Thrown by ListResultsConsumer.readUniqueAssert when a query runs under UniqueSemantic.ASSERT: every row read must be distinct, and results.addUnique detected a row equal (per the result JavaType) to one already collected. ASSERT is applied primarily by the internal by-id load plan (SingleIdLoadPlan uses ASSERT when a single result is expected), i.e. `EntityManager.find`/`session.find`, and only when the row reader has no collection initializers. Genuine duplicates for a primary-key load mean the mapping does not guarantee one row per id.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/spi/ListResultsConsumer.java:262
RowReader<R> rowReader,
Results<R> results) {
int readRows = 0;
while ( rowProcessingState.next() ) {
results.add( rowReader.readRow( rowProcessingState ) );
rowProcessingState.finishRowProcessing( true );
readRows++;
}
return readRows;
}
private static <R> int readUniqueAssert(
RowProcessingStateStandardImpl rowProcessingState,
RowReader<R> rowReader,
Results<R> results) {
int readRows = 0;
while ( rowProcessingState.next() ) {
if ( !results.addUnique( rowReader.readRow( rowProcessingState ) ) ) {
throw new HibernateException(
String.format(
Locale.ROOT,
"Duplicate row was found and `%s` was specified",
UniqueSemantic.ASSERT
)
);
}
rowProcessingState.finishRowProcessing( true );
readRows++;
}
return readRows;
}
private static <R> int readUnique(
RowProcessingStateStandardImpl rowProcessingState,
RowReader<R> rowReader,
Results<R> results) {
int readRows = 0;View on GitHub (pinned to fad1729dce)
Solutions
- Fix the underlying data or mapping so at most one row exists per primary key (dedupe the view/table, add the missing unique constraint)
- For JOINED inheritance, delete the duplicate id rows from the extra subclass table(s) so each id lives in exactly one subclass
- Fix custom `@Loader`/`@SQLSelect` SQL to return a unique row (add the right predicate or `distinct` on the id)
- As a stopgap, load via a query with `UniqueSemantic`-tolerant semantics (e.g. a plain JPQL `where e.id = :id`) instead of `find()` to observe the duplicates, then fix the data
Example fix
// before: entity mapped to a view with duplicate ids -> em.find throws Employee e = em.find(Employee.class, id); // after: dedupe the view (SQL) so each id appears once, keep em.find create view employee_v as select distinct on (id) * from employee_raw;
Defensive patterns
Strategy: validation
Validate before calling
// Prove the load key is unique before relying on em.find (e.g. for view-backed entities)
Long cnt = em.createQuery("select count(*) from EmployeeViewBacked e where e.businessKey = :k", Long.class)
.setParameter("k", key).getSingleResult();
if (cnt != 1) throw new IllegalStateException("Load key not unique: " + key + " (" + cnt + " rows)"); Try / catch
catch (org.hibernate.HibernateException e) { if (e.getMessage() != null && e.getMessage().contains("Duplicate row was found")) { /* data issue: dedupe, fix view/inheritance/custom loader */ } throw e; } Prevention
- Back by-id loads with a real primary key or unique constraint (views need a unique key too)
- For JOINED inheritance, keep each id in exactly one subclass table - enforce and monitor this
- Test custom @Loader/@SQLSelect SQL returns exactly one row for one id
- Add a data-quality check for duplicate ids on view/denormalized tables in CI or ops dashboards
When it happens
Trigger: `em.find(Employee.class, id)` where the entity is mapped to a database view containing the id twice; JOINED inheritance with the same id present in two subclass tables; a custom `@Loader`/`@SQLSelect` returning the same id more than once; broken data where a 'unique' key used for loading is not actually unique.
Common situations: Read-only reporting entities mapped onto views without a unique key; denormalized tables feeding entity mappings; data corruption or manual inserts breaking subclass-table uniqueness; custom loader SQL with an accidental cross join duplicating rows.
Related errors
- No add primary key syntax supported by SQLiteDialect
- SingleStore does not support altering primary key.
- No row with the given identifier exists for entity " + infoS
- Cannot add primary key constraint in Cloud Spanner.
- Dialect returns null TemporaryTableStrategy for temporary ta
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/28cb8f070122219a.
Report an issue: GitHub.