hibernate/hibernate-orm · error · HibernateException
Immutable collection dereferenced by owner: {}
Error message
Immutable collection dereferenced by owner: {} What it means
checkOnChangedOwner validates collections whose entry is read-only (loaded as immutable - read-only session/entity or immutable mapping). If such a collection is dereferenced (the owner's property now points at a different collection or null) while the owner is still alive (not deleted/gone), Hibernate throws: an immutable collection cannot be replaced, because the loaded state is the database truth and no snapshot/update path exists for it.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/internal/Collections.java:302
else if ( collection.isDirty() ) {
// the collection's elements have changed
flushProcessingContext.queueCollectionUpdate(
collection,
loadedPersister,
collectionEntry.getLoadedKey(),
collectionEntry.isSnapshotEmpty( collection )
);
}
}
}
private static void checkOnChangedOwner(PersistentCollection<?> collection, CollectionEntry collectionEntry, CollectionPersister loadedPersister, CollectionPersister currentPersister) {
final boolean immutableDereferenced =
collectionEntry.isReadOnly()
&& loadedPersister != null
&& !isOwnerDeletedOrGone( collection );
if ( immutableDereferenced ) {
throw new HibernateException( "Immutable collection dereferenced by owner: "
+ collectionInfoString( loadedPersister.getRole(), collectionEntry.getLoadedKey() ) );
}
final boolean orphanDeleteAndRoleChanged =
loadedPersister != null
&& currentPersister != null
&& loadedPersister.hasOrphanDelete();
if ( orphanDeleteAndRoleChanged ) {
throw new HibernateException(
"Collection with orphan orphan delete enabled has modifier owner: "
+ collectionInfoString( loadedPersister.getRole(), collectionEntry.getLoadedKey() ) );
}
}
private static boolean isOwnerDeletedOrGone(PersistentCollection<?> collection) {
final Object owner = collection.getOwner();
assert owner != null;View on GitHub (pinned to fad1729dce)
Solutions
- Load the entity in read-write mode before modifying it: session.setDefaultReadOnly(false) / avoid readOnly() on the load.
- Make the collection mapping mutable (remove immutable=true / ensure the owner is not loaded read-only).
- Do not replace the collection on read-only entities - delete and reinsert the owner if the data must change.
- Check collectionInfoString in the message to identify which role/owner triggered it and fix that code path.
Example fix
// before - entity loaded read-only, collection replaced Session ro = sf.withOptions().readOnly(true).openSession(); Order o = ro.find(Order.class, id); o.setLines(new ArrayList<>()); // dereference -> HibernateException at flush // after - load read-write for modification Session rw = sf.openSession(); Order o = rw.find(Order.class, id); o.getLines().clear();
Defensive patterns
Strategy: validation
Validate before calling
// Guard: verify the entity is writable before letting code replace its collections
boolean writable = session.getEntityPersister(null, entity).isMutable()
&& !session.isReadOnly(entity);
if (!writable) throw new IllegalStateException(
"Entity loaded read-only; collection replacement not allowed - reload read-write first"); Try / catch
catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Immutable collection dereferenced by owner")) {
// reload the owner in a read-write session before editing
throw new MappingMisuseException(e.getMessage(), e);
}
throw e;
} Prevention
- Keep read-only loads strictly read: separate report sessions from edit sessions.
- Check session.isReadOnly(entity) in update flows before mutating collections.
- Do not map collections as immutable if the application ever needs to replace them.
When it happens
Trigger: Calling a setter that replaces a collection on an entity loaded read-only (session.setDefaultReadOnly(true), sharedSessionBuilder .readOnly(true), @Immutable-adjacent read-only entries), or a collection mapped immutable, then dereferencing it (set X(null) or setX(newCollection)) and flushing while the owner is managed.
Common situations: Read-only report sessions upgraded to write sessions; entities loaded with LockOptions.READ_ONLY then modified; mapping collections to immutable where the UI still lets users replace lists; load-then-modify flows on top of 'optimization' read-only flags.
Related errors
- A collection with orphan deletion was no longer referenced b
- Can't update read-only object
- Can't write to a read-only object
- Found two representations of same collection: {}
- Found shared references to a collection: {}
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e7ca0d4eb0615bea.
Report an issue: GitHub.