hibernate/hibernate-orm · critical · ConcurrentModificationException
Found a different instance corresponding to instanceId [${in
Error message
Found a different instance corresponding to instanceId [${instanceId}], this might indicate a concurrent access to this persistence context. What it means
InstanceIdentityStore.get(Object key, int instanceId) reads the key slot for instanceId (keys and values occupy adjacent slots: offset and offset+1) and checks k == key. A different object in the slot means the same instance id maps to two distinct instances — only possible if the store/persistence context is accessed concurrently — so it throws ConcurrentModificationException naming the instanceId. It is an integrity alarm, not a normal miss (misses return null).
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/util/collections/InstanceIdentityStore.java:63
* @implNote This method accesses the backing array with the provided instance id, but performs an instance
* equality check ({@code ==}) with the provided key to ensure it corresponds to the mapped one
*/
public @Nullable V get(int instanceId, Object key) {
if ( instanceId <= 0 ) {
return null;
}
final int keyIndex = toKeyIndex( instanceId );
final Page<Object> page = getPage( keyIndex );
if ( page != null ) {
final int offset = toPageOffset( keyIndex );
final Object k = page.get( offset );
if ( k == key ) {
//noinspection unchecked
return (V) page.get( offset + 1 );
}
else {
throw new ConcurrentModificationException(
"Found a different instance corresponding to instanceId [" + instanceId +
"], this might indicate a concurrent access to this persistence context."
);
}
}
return null;
}
/**
* Associates the specified value with the specified key in this store (optional operation). If the store
* previously contained a mapping for the key, the old value is replaced by the specified value.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
*/
public void put(Object key, int instanceId, V value) {
if ( key == null ) {
throw new NullPointerException( "This store does not support null keys" );View on GitHub (pinned to fad1729dce)
Solutions
- Give each thread its own Session; the persistence context is single-threaded by contract
- Synchronize all external access to shared persistence-context state if sharing is unavoidable
- Log thread names on every session operation during the investigation to find the second actor
- Close the corrupted Session; do not attempt to repair it mid-flight
Example fix
// before Object cached = store.get( entity, id ); // entity id reused across threads // after: verify same-instance usage and single-threaded context assert Thread.currentThread() == ownerThread; Object cached = ( entity == lastPut ) ? store.get( entity, id ) : null;
Defensive patterns
Strategy: try-catch
Try / catch
try {
return store.get( key, instanceId );
} catch ( ConcurrentModificationException e ) {
// instance identity corrupted by concurrent access — abort, close session
throw new IllegalStateException("Persistence context accessed concurrently", e);
} Prevention
- Treat the persistence context as thread-confined; open a Session per thread/task
- Never cache Sessions in shared fields or thread-local pools spanning tasks
- Reproduce suspected races with concurrent integration tests before they surface in production
When it happens
Trigger: Thread B put() a different key under the same instanceId between thread A's slot read and identity check; the store is not internally synchronized, so any cross-thread sharing of the owning persistence context can interleave this way.
Common situations: One Hibernate Session used from multiple threads (parallel streams triggering lazy loads, @Async handlers, hand-rolled pools); tests that hammer a Session from several threads to 'speed up' setup.
Related errors
- Found a different instance corresponding to instanceId [${in
- No row with the given identifier exists for entity " + infoS
- Newer version [" + latestVersion + "] of entity [" + infoStr
- %s for entity %s#%s
- Illegal attempt to associate a collection with two open sess
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/496fcff2756e03d6.
Report an issue: GitHub.