hibernate/hibernate-orm · error · HibernateException

Could not reassociate uninitialized transient collection

Error message

Could not reassociate uninitialized transient collection

What it means

HibernateException from ProxyVisitor.reattachCollection: while reattaching a detached entity's collection during lock/refresh-style reattach (the AbstractReattachEventListener proxy visitor path), an uninitialized PersistentCollection failed isCollectionSnapshotValid — its getRole() or getKey() is null. A collection wrapper with no role/key snapshot was never properly associated with a session, i.e. it is effectively transient, so there is nothing to reassociate it with.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/event/internal/ProxyVisitor.java:60

	}

	/**
	 * Reattach a detached (disassociated) initialized or uninitialized
	 * collection wrapper, using a snapshot carried with the collection
	 * wrapper
	 */
	protected void reattachCollection(@Nonnull PersistentCollection<?> collection, @Nonnull CollectionType type)
			throws HibernateException {
		final var session = getSession();
		final var metamodel = session.getFactory().getMappingMetamodel();
		final var context = session.getPersistenceContext();
		if ( collection.wasInitialized() ) {
			final var persister = metamodel.getCollectionDescriptor( type.getRole() );
			context.addInitializedDetachedCollection( persister, collection );
		}
		else {
			if ( !isCollectionSnapshotValid( collection ) ) {
				throw new HibernateException( "Could not reassociate uninitialized transient collection" );
			}
			final var persister = metamodel.getCollectionDescriptor( collection.getRole() );
			context.addUninitializedDetachedCollection( persister, collection );
		}
	}

}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use session.merge(entity) instead of lock()/update() for reattachment — merge copies state onto loaded instances and does not need the old wrapper's snapshot
  2. Ensure detached entities keep their original Hibernate collection instances (don't replace collection fields after load; don't deep-copy wrappers)
  3. For genuinely new entities, save/persist them instead of reattaching; fix the application logic that labels transient instances as detached

Example fix

// before
// detached order whose items field was replaced with a plain ArrayList after load
session.buildLockRequest(LockOptions.NONE).lock(order); // could not reassociate uninitialized transient collection

// after
Order managed = (Order) session.merge(order); // merge copies state, no snapshot needed
Defensive patterns

Strategy: fallback

Validate before calling

if (order instanceof HibernateProxy || Hibernate.isPropertyInitialized(order, "items")) {
    if (order.getItems() != null && Hibernate.isInitialized(order.getItems())) {
        // safe to reattach
    }
}
// simplest: ensure managed collections stay attached by using merge() for detached graphs

Type guard

boolean safeToReattach(Object entity, String collectionField) {
    return Hibernate.isPropertyInitialized(entity, collectionField)
            && Hibernate.isInitialized(getter(entity, collectionField));
}

Try / catch

try {
    session.buildLockRequest(LockOptions.NONE).lock(order);
} catch (HibernateException e) {
    if ("Could not reassociate uninitialized transient collection".equals(e.getMessage())) {
        order = (Order) session.merge(order); // fallback: merge does not need the snapshot
    } else { throw e; }
}

Prevention

When it happens

Trigger: session.lock(detachedEntity, LockMode.NONE) (or another reattach-based API) on a detached entity whose uninitialized lazy collection wrapper lost its snapshot — e.g. the collection field was replaced with a bare java.util collection that Hibernate wrapped fresh without a role/key, or a new entity instance with 'new ArrayList<>()' assigned is mistaken for detached state; deserialized/mutated wrappers whose role metadata is gone.

Common situations: Calling update()/lock() (reattach semantics) on entities that are actually transient or whose collection fields were swapped after load; mixing merge-style and update-style handling of the same object graph; deep-copy/serialization utilities that drop the PersistentCollection internals; upgrading code that relied on lenient reattachment behavior of older Hibernate versions.

Related errors


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