hibernate/hibernate-orm · error · HibernateException
Flush during cascade is dangerous
Error message
Flush during cascade is dangerous
What it means
SessionImpl.fireFlush() refuses to flush while persistenceContext.getCascadeLevel() > 0 — i.e. while Hibernate is in the middle of cascading save/delete through an object graph. Flushing mid-cascade can reorder SQL and re-save or lose entities, so HibernateException('Flush during cascade is dangerous') aborts it. The check applies to explicit flush() and internal transactional flushes that route through fireFlush().
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java:1460
.fireEventOnEachListener( dirtyCheckEvent,
DirtyCheckEventListener::onDirtyCheck );
return dirtyCheckEvent.isDirty();
}
}
@Override
public void flush() {
checkOpen();
fireFlush();
}
private void fireFlush() {
if ( !isReadOnly() ) {
try {
pulseTransactionCoordinator();
checkTransactionNeededForUpdateOperation();
if ( persistenceContext.getCascadeLevel() > 0 ) {
throw new HibernateException( "Flush during cascade is dangerous" );
}
eventListenerGroups.eventListenerGroup_FLUSH
.fireEventOnEachListener( new FlushEvent( this ),
FlushEventListener::onFlush );
delayedAfterCompletion();
}
catch (RuntimeException e) {
throw getExceptionConverter().convert( e );
}
}
}
/**
* Used for auto flushing shared/child session as part of the parent session's auto flush.
*/
@Override
public void propagateFlush() {
if ( isClosed() ) {View on GitHub (pinned to fad1729dce)
Solutions
- Move the flush out of the listener/interceptor: collect work in the listener, perform it after the save cascade completes
- Do not run queries with auto-flush inside callbacks; defer to after-commit hooks or @Transactional boundaries
- If early SQL is required, restructure so the callback only mutates state and the container flushes normally at commit
- Audit via Envers/hibernate-envers or transaction hooks instead of querying inside callbacks
Example fix
// before
@PrePersist
void onPrePersist() {
auditRepo.log(this); // internally queries -> flush during cascade -> HibernateException
}
// after
@PrePersist
void onPrePersist() {
AuditQueue.enqueue(this); // just record, no DB access
}
// flush/insert happens after the cascade, e.g. in an entity listener registered via
// EventListenerGroup or after transaction completion Defensive patterns
Strategy: try-catch
Validate before calling
// Inside listeners/interceptors, defer DB work instead of flushing
if (session.getPersistenceContext().getCascadeLevel() > 0) {
AuditQueue.enqueue(this); // defer: no flush/query during cascade
} else {
auditRepo.log(this);
} Try / catch
try {
session.flush();
} catch (HibernateException e) {
if (e.getMessage().contains("Flush during cascade")) {
// we are inside a cascade callback: defer the flush to commit time
deferredFlushRequired = true;
} else {
throw e;
}
} Prevention
- Never call repository/query APIs from @PrePersist/@PreUpdate listeners or interceptor callbacks
- Collect side effects in listeners and apply them after the cascade or transaction completes
- Keep entity listeners free of Session/EntityManager usage; use Envers or event listeners registered at the factory level for auditing
When it happens
Trigger: Calling session.flush() (directly or via query with FlushMode.AUTO triggering a managed flush) from inside an entity listener (@PrePersist/@PreUpdate), an Interceptor, a cascade callback, or an association action that runs while the cascade level is elevated. Typical: flush in onPersist listener, or executing a query inside onSave of a custom interceptor.
Common situations: Business logic inside JPA entity listeners that calls repository save (which flushes); interceptors doing audit queries at onSave time; flush-mode AUTO queries executed from within event listeners; recursive saves where application code flushes inside cascade-driven hooks.
Related errors
- Session method called from entity lifecycle callback or Inte
- Instance of '" + entityName + "' references an unsaved trans
- Instance of '%s' references an unsaved transient instance of
- There are delayed insert actions before operation as cascade
- deleted object would be re-saved by cascade (remove deleted
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/2730f4e91e2c3c88.
Report an issue: GitHub.