hibernate/hibernate-orm · error · ObjectDeletedException
Given entity was removed
Error message
Given entity was removed
What it means
getCurrentLockMode() reads the EntityEntry of the object; if its status is DELETED/GONE the entity has been removed in this session (remove() scheduled or already flushed), and Hibernate throws ObjectDeletedException('Given entity was removed'). A deleted entity has no ongoing lock semantics — asking for its lock mode is a state error, not a missing-data error.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java:559
@Override
public LockMode getCurrentLockMode(Object object) {
checkOpen();
checkTransactionSyncStatus();
if ( object == null ) {
throw new NullPointerException( "null object passed to getCurrentLockMode()" );
}
final var lazyInitializer = extractLazyInitializer( object );
if ( lazyInitializer != null ) {
object = lazyInitializer.getImplementation( this );
if ( object == null ) {
return LockMode.NONE;
}
}
final var entry = getEntityEntry( object );
if ( entry.getStatus().isDeletedOrGone() ) {
throw new ObjectDeletedException( "Given entity was removed", entry.getId(),
entry.getPersister().getEntityName() );
}
else {
return entry.getLockMode();
}
}
@Override
public Object getEntityUsingInterceptor(@Nonnull EntityKey key) {
checkOpenOrWaitingForAutoClose();
// todo : should this get moved to PersistentContext?
// logically, is PersistentContext the "thing" to which an interceptor gets attached?
final Object result = persistenceContext.getEntity( key );
if ( result == null ) {
final Object newObject = callInterceptorCallback(
() -> getInterceptor().getEntity( key.getEntityName(), key.getIdentifier() ) );
if ( newObject != null ) {
lock( newObject, LockMode.NONE );View on GitHub (pinned to fad1729dce)
Solutions
- Skip lock inspection for removed entities: check entry status via session.getPersistenceContext().getEntry(obj) or track removed identities in a Set
- Reorder the flow: capture getCurrentLockMode() before remove(), not after
- If the entity must survive, avoid the remove or clear/reattach a different instance
- Catch ObjectDeletedException in generic monitoring code and treat it as 'no lock mode (deleted)'
Example fix
// before session.remove(order); logLock(session.getCurrentLockMode(order)); // ObjectDeletedException // after LockMode mode = session.getCurrentLockMode(order); // inspect first session.remove(order); logLock(mode);
Defensive patterns
Strategy: try-catch
Validate before calling
// Skip deleted entities before asking for their lock mode
EntityEntry entry = session.getPersistenceContext().getEntry(object);
if (entry == null || entry.getStatus().isDeletedOrGone()) {
return LockMode.NONE; // or skip audit record
}
return session.getCurrentLockMode(object); Try / catch
try {
return session.getCurrentLockMode(object);
} catch (ObjectDeletedException e) {
// entity already removed in this session — no lock mode exists
LOG.debug("lock mode requested for deleted entity {}", e.getEntityName());
return LockMode.NONE;
} Prevention
- Inspect lock modes before remove(), not after
- Track removed entities in a Set when audit code runs after delete branches
- In generic frameworks, treat ObjectDeletedException as a normal 'no state' signal rather than an error
When it happens
Trigger: Calling session.getCurrentLockMode(entity) after session.remove(entity) (or orphanRemoval marking it) within the same session/transaction, before or after flush. Also via cascade-delete: a child deleted by cascade then queried for lock mode.
Common situations: Audit/logging code that records lock modes for all processed entities and runs after a delete branch; generic frameworks intercepting remove() and then inspecting lock state; flows where the same object instance is reused for delete and later inspection in one transaction.
Related errors
- null object passed to getCurrentLockMode()
- WRITE is not a valid LockMode as an argument
- Cannot lazily initialize collection
- Illegal attempt to associate a collection with two open sess
- Lock mode ${lockMode} not valid for locking via 'update' sta
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/9eabfea707d356ac.
Report an issue: GitHub.