hibernate/hibernate-orm · error · IllegalStateException
There are delayed insert actions before operation as cascade
Error message
There are delayed insert actions before operation as cascade level 0.
What it means
With identity-style immediate inserts (IDENTITY generation, or inserts queued via ActionQueue), Hibernate can end a unit of work with 'unresolved entity insert actions' — inserts held back because they participate in circular FK dependencies. Operations such as lock() call checkNoUnresolvedActionsBeforeOperation(), which refuses to run while such actions are pending at cascade level 0, throwing IllegalStateException. This guards against executing an operation whose outcome could depend on un-flushed insert state.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java:588
// 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 );
}
return newObject;
}
else {
return result;
}
}
protected void checkNoUnresolvedActionsBeforeOperation() {
if ( persistenceContext.getCascadeLevel() == 0 && actionQueue.hasUnresolvedEntityInsertActions() ) {
throw new IllegalStateException( "There are delayed insert actions before operation as cascade level 0." );
}
}
protected void checkNoUnresolvedActionsAfterOperation() {
if ( persistenceContext.getCascadeLevel() == 0 ) {
actionQueue.checkNoUnresolvedActionsAfterOperation();
}
delayedAfterCompletion();
}
@Override
public void delayedAfterCompletion() {
super.delayedAfterCompletion();
}
@Override
public void pulseTransactionCoordinator() {
super.pulseTransactionCoordinator();View on GitHub (pinned to fad1729dce)
Solutions
- Flush first: session.flush() resolves the pending insert actions before the guarded operation
- Switch identifier generation to SEQUENCE (or pooled/table) so inserts are not forced through the unresolved-action queue
- Break the FK cycle: make one side nullable and set the association after both saves, or use join-table mapping
- Reorder the code so lock/refresh happens before persisting the circular graph
Example fix
// before (Order.id is IDENTITY, Order.customer <-> Customer.orders circular FK) session.persist(order); session.lock(customer, LockMode.NONE); // IllegalStateException: delayed insert actions // after session.persist(order); session.flush(); // resolve delayed insert actions first session.lock(customer, LockMode.NONE);
Defensive patterns
Strategy: try-catch
Validate before calling
// Flush resolves pending identity inserts before guarded operations
if (!session.getActionQueue().hasUnresolvedEntityInsertActions()) {
session.lock(entity, LockMode.NONE);
} else {
session.flush();
session.lock(entity, LockMode.NONE);
} Try / catch
try {
session.lock(entity, LockMode.NONE);
} catch (IllegalStateException e) {
if (e.getMessage().contains("delayed insert actions")) {
session.flush(); // resolve the delayed inserts
session.lock(entity, LockMode.NONE); // retry once
} else {
throw e;
}
} Prevention
- Prefer SEQUENCE identifier generation over IDENTITY to avoid unresolved-insert queues entirely
- Avoid circular FK references between newly created entities; set one side after both are persisted
- Flush after persisting graphs with IDENTITY keys before performing lock/refresh operations
When it happens
Trigger: Persisting entities with IDENTITY identifiers involved in bidirectional FK cycles, then calling session.lock/refresh/get-style guarded operations before a flush resolves the queue. Triggered when persistenceContext.getCascadeLevel() == 0 and actionQueue.hasUnresolvedEntityInsertActions().
Common situations: Parent/child mutual references with IDENTITY keys on MySQL/SQL Server (no sequences); circular foreign keys between two new entities; legacy schemas forcing IDENTITY; operations triggered lazily (lazy loading forcing the check) right after saving such a graph.
Related errors
- Instance of '" + entityName + "' references an unsaved trans
- Instance of '%s' references an unsaved transient instance of
- Unsupported JdbcOperation type: %s
- Unbreakable unique update cycle detected for SCC: %s
- Unbreakable cycle detected for SCC: %s
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1b1f5ca91ff4ab55.
Report an issue: GitHub.