hibernate/hibernate-orm · error · StaleObjectStateException
Persistence context contains a more recent version of the gi
Error message
Persistence context contains a more recent version of the given entity
What it means
While deleting a detached entity, flushAndEvictExistingEntity() finds a managed instance under the same key in the persistence context, flushes, and compares versions: the managed copy's version differs, so the detached copy you passed is stale. Hibernate throws StaleObjectStateException('Persistence context contains a more recent version of the given entity') — optimistic locking applied on the remove path.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java:236
@Nonnull EventSource source) {
final var persistenceContext = source.getPersistenceContextInternal();
final Object existingEntity = persistenceContext.getEntity( key );
if ( existingEntity != null ) {
if ( persistenceContext.getEntry( existingEntity ).getStatus().isDeletedOrGone() ) {
// already deleted, no work to do
return true;
}
else {
EVENT_LISTENER_LOGGER.flushAndEvictOnRemove( key.getEntityName() );
source.flush();
if ( !persister.isVersioned()
|| persister.getVersionType()
.isEqual( version, persister.getVersion( existingEntity ) ) ) {
source.evict( existingEntity );
return false;
}
else {
throw new StaleObjectStateException( key.getEntityName(), key.getIdentifier(),
"Persistence context contains a more recent version of the given entity" );
}
}
}
else {
return false;
}
}
private void deletePersistentInstance(
@Nonnull DeleteEvent event,
@Nonnull DeleteContext transientEntities,
@Nonnull Object entity,
@Nonnull EntityEntry entityEntry) {
EVENT_LISTENER_LOGGER.deletingPersistentInstance();
final var source = event.getSession();
if ( entityEntry.getStatus().isDeletedOrGone()
|| source.getPersistenceContextInternal()View on GitHub (pinned to fad1729dce)
Solutions
- Use merge() before remove so the version is reconciled against the managed copy
- Re-fetch fresh state in the current session and delete that: session.remove(session.find(X.class, id))
- Catch StaleObjectStateException and either retry the unit of work from fresh state or report a conflict
- Avoid carrying detached instances across long conversations without version checks
Example fix
// before session.remove(staleOrder); // session manages a newer version -> StaleObjectStateException // after Order fresh = session.find(Order.class, staleOrder.getId()); session.remove(fresh);
Defensive patterns
Strategy: retry
Validate before calling
// avoid the stale path: delete the managed, most recent version
Order fresh = session.find(Order.class, detached.getId());
if (fresh != null) {
session.remove(fresh);
} Try / catch
try {
session.remove(detachedOrder);
} catch (StaleObjectStateException e) {
// persistence context has a newer version: reload fresh state and retry once
Order fresh = session.find(Order.class, detachedOrder.getId());
session.remove(fresh);
} Prevention
- merge() before remove() so versions are reconciled
- Re-fetch entities inside the transaction that deletes them
- Keep sessions/transactions short when @Version columns are used
- Handle StaleObjectStateException explicitly at the use-case boundary
When it happens
Trigger: session.remove(detachedEntity) while the same session manages a newer version of that row (loaded after your detached copy was read); a detached instance built from stale state mixed back into an active session; two loads of the same row in one conversation with a bump in between.
Common situations: Long conversations with detached reattachment; delete flows fed by cached/stale frontend state while background jobs bumped the version; optimistic-lock @Version columns added to entities used in delete paths.
Related errors
- Newer version [" + latestVersion + "] of entity [" + infoStr
- Cannot delete instance of entity '${persister.getEntityName(
- Unexpected row count (expected row count {} but was {}) [{}]
- Entity '{name}' has 'OptimisticLockType.{optimisticLockStyle
- Query result contains conflicting version of entity already
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b15120fcb62ac72d.
Report an issue: GitHub.