hibernate/hibernate-orm · error · HibernateException

Illegal attempt to associate a collection with two open sess

Error message

Illegal attempt to associate a collection with two open sessions: 

What it means

A PersistentCollection tracks the session it belongs to; setCurrentSession attaches it when an entity graph enters a session. If the collection is still connected to another open session, Hibernate throws this HibernateException: one collection instance cannot be managed by two open sessions at once. It signals managed entity instances (with their associations) shared across concurrent sessions.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java:773

			allowLoadOutsideTransaction =
					factory.getSessionFactoryOptions()
							.isInitializeLazyStateOutsideTransactionsEnabled();

			if ( allowLoadOutsideTransaction && sessionFactoryUuid == null ) {
				sessionFactoryUuid = factory.getUuid();
			}
		}
	}

	@Override
	public final boolean setCurrentSession(SharedSessionContractImplementor session) throws HibernateException {
		if ( session == this.session ) {
			return false;
		}
		else if ( this.session != null ) {
			final String message = unexpectedSessionStateMessage( session );
			if ( isConnectedToSession() ) {
				throw new HibernateException(
						"Illegal attempt to associate a collection with two open sessions: " + message
				);
			}
			else {
				COLLECTION_LOGGER.logUnexpectedSessionInCollectionNotConnected( message );
			}
		}
		if ( hasQueuedOperations() ) {
			COLLECTION_LOGGER.queuedOperationWhenAttachToSession(
					collectionInfoString( getRole(), getKey() ) );
		}
		this.session = session;
		return true;
	}

	private String unexpectedSessionStateMessage(SharedSessionContractImplementor session) {
		// NOTE: If this.session != null, this.session may be operating on this collection
		// (e.g., by changing this.role, this.key, or even this.session) in a different thread.

View on GitHub (pinned to fad1729dce)

Solutions

  1. Do not share managed instances: re-load by id in each session, or cache ids/DTOs instead of entities
  2. Use merge() from a clean detached state instead of attaching a shared instance to a second open session
  3. Close or evict the entity from the first session before reattaching it elsewhere
  4. Scope one session per unit of work per thread

Example fix

// before
Order shared = session1.find(Order.class, id); // session1 still open
session2.update(shared); // -> Illegal attempt to associate a collection with two open sessions

// after
Order fresh = session2.find(Order.class, id); // or session2.merge(sharedDetached) after session1 closed
Defensive patterns

Strategy: validation

Validate before calling

// only reattach a shared entity after its original session is gone
if (sharedOrder != null && originalSession.isOpen()) {
    originalSession.evict(sharedOrder); // detach first
}
targetSession.update(sharedOrder);

Try / catch

try {
    session2.update(sharedEntity);
} catch (HibernateException e) {
    if (e.getMessage() != null
            && e.getMessage().startsWith("Illegal attempt to associate a collection")) {
        session2.evict(sharedEntity);
        sharedEntity = session2.merge(sharedEntity); // proper reattach path
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: session2.update(sharedEntity) while session1 that loaded the entity is still open; caching managed entities in application code and reusing them across requests or threads; parallel processing touching lazy collections attached to different sessions.

Common situations: Application-level caches holding managed entities; entities passed between threads; two open EntityManagers in one request; long-lived session misuse.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/63b4ff5c9cd07ece. Report an issue: GitHub.