hibernate/hibernate-orm · error · HibernateException
Illegal attempt to associate a ManagedEntity with two open p
Error message
Illegal attempt to associate a ManagedEntity with two open persistence contexts: {} What it means
For bytecode-enhanced entities (ManagedEntity), Hibernate stores the EntityEntry inside the entity itself. When such an entity - already carrying an EntityEntry whose persistence context is a DIFFERENT, still-open session - is added to this EntityEntryContext, and the entity's persister is mutable, Hibernate throws: the other session (possibly another thread) may still be using that injected entry, so associating it here would corrupt both sessions. A closed other context is tolerated with a stale-entry log.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryContext.java:214
}
private void putImmutableManagedEntity(ManagedEntity managed, int instanceId, ImmutableManagedEntityHolder holder) {
if ( immutableManagedEntityXref == null ) {
immutableManagedEntityXref = new InstanceIdentityStore<>();
}
immutableManagedEntityXref.put( managed, instanceId, holder );
}
private void checkNotAssociatedWithOtherPersistenceContextIfMutable(ManagedEntity managedEntity) {
// we only have to check mutable managedEntity
final var entityEntry = (EntityEntryImpl) managedEntity.$$_hibernate_getEntityEntry();
if ( entityEntry != null && entityEntry.getPersister().isMutable() ) {
final var entryPersistenceContext = entityEntry.getPersistenceContext();
if ( entryPersistenceContext != null && entryPersistenceContext != persistenceContext ) {
if ( entryPersistenceContext.getSession().isOpen() ) {
// NOTE: otherPersistenceContext may be operating on the entityEntry in a different thread.
// it is not safe to associate entityEntry with this EntityEntryContext.
throw new HibernateException(
"Illegal attempt to associate a ManagedEntity with two open persistence contexts: " + entityEntry
);
}
else {
// otherPersistenceContext is associated with a closed PersistenceContext
CORE_LOGGER.stalePersistenceContextInEntityEntry( entityEntry.toString() );
}
}
}
}
/**
* Does this entity exist in this context, associated with an {@link EntityEntry}?
*
* @param entity The entity to check
*
* @return {@code true} if it is associated with this context
*/View on GitHub (pinned to fad1729dce)
Solutions
- Close (or clear) the first session before handing the entity to another session - with the origin context closed, Hibernate logs a stale entry and proceeds.
- Use merge() semantics on a detached COPY rather than re-associating the same enhanced instance into a second open session.
- Do not cache enhanced entities across requests; cache DTOs or ids and reload per session.
- Ensure one thread/session 'owns' an entity at a time; never operate the same enhanced instance from two open sessions concurrently.
Example fix
// before - enhanced entity attached to two open sessions
try (Session a = sf.openSession()) { orderA = a.find(Order.class, id); }
// session a still open elsewhere; then:
try (Session b = sf.openSession()) {
b.lock(orderA, LockMode.NONE); // Illegal attempt ...
}
// after - close the first session, or merge a copy
try (Session b = sf.openSession()) {
Order managed = b.merge(orderA); // detached copy gets its own entry
} Defensive patterns
Strategy: validation
Validate before calling
// Guard: before attaching an enhanced entity to a new session, check its current entry
static boolean isAttachedToOpenSession(Object entity) {
if (entity instanceof org.hibernate.engine.spi.ManagedEntity me) {
var entry = me.$$_hibernate_getEntityEntry();
return entry != null
&& entry.getPersistenceContext() != null
&& entry.getPersistenceContext().getSession().isOpen();
}
return false;
}
// if (isAttachedToOpenSession(order)) order = newSession.merge(order); Type guard
static boolean isManagedEntity(Object o) {
return o instanceof org.hibernate.engine.spi.ManagedEntity;
} Try / catch
catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Illegal attempt to associate a ManagedEntity")) {
// close/clear the original session, or merge a copy instead of re-associating
target = session.merge(detachedCopy);
} else throw e;
} Prevention
- Scope enhanced entities to one open session; close or clear the origin session before cross-session use.
- Pass detached copies or ids between layers instead of live enhanced instances.
- Never touch the same enhanced entity from two open sessions on different threads.
When it happens
Trigger: Loading a bytecode-enhanced entity in session A, then while A is still open passing that same instance to session B (merge/lock/refresh/saveOrUpdate/reference) so B tries to attach it; also concurrent use of one entity across threads/sessions. The check only fires for mutable persisters - immutable entities can float between contexts.
Common situations: Build-time or runtime bytecode enhancement enabled (lazy-loading/dirty-tracking instrumentation) plus code that reuses detached-ish entities in a new open session; long-lived entities cached in application memory and fed into request sessions; async processing where the originating session stays open on another thread; test suites leaking sessions per class.
Related errors
- A different object with the same identifier value was alread
- Given entity is not associated with the persistence context
- Found a different instance corresponding to instanceId [${in
- Failed to enhance class {className}
- Failed to discover types for class {className}
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/634e298ec01527be.
Report an issue: GitHub.