hibernate/hibernate-orm · error · HibernateException
Unable to register cleanup Synchronization with TransactionM
Error message
Unable to register cleanup Synchronization with TransactionManager
What it means
After building a session for the current JTA transaction, JTASessionContext registers a Synchronization on that transaction so the session is removed from the map when the transaction completes. If Transaction.registerSynchronization() throws — transaction already completed, marked rollback-only, or TM-specific restrictions — Hibernate closes the freshly built session and throws this HibernateException.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/context/internal/JTASessionContext.java:94
else {
validateExistingSession( currentSession );
}
return currentSession;
}
private void registerSynchronization(Transaction txn, Object txnIdentifier, Session currentSession) {
try {
txn.registerSynchronization( buildCleanupSynch( txnIdentifier ) );
}
catch ( Throwable t ) {
try {
currentSession.close();
}
catch ( Throwable e ) {
CURRENT_SESSION_LOGGER.unableToReleaseGeneratedCurrentSessionOnFailedSynchronizationRegistration(e);
}
throw new HibernateException( "Unable to register cleanup Synchronization with TransactionManager" );
}
}
private static @Nonnull Transaction getTransaction(TransactionManager transactionManager) {
try {
final var transaction = transactionManager.getTransaction();
if ( transaction == null ) {
throw new HibernateException( "Unable to locate current JTA transaction" );
}
if ( !isActive( transaction.getStatus() ) ) {
// We could register the session against the transaction even though it is
// not started, but we'd have no guarantee of ever getting the map
// entries cleaned up (aside from spawning threads).
throw new HibernateException( "Current transaction is not in progress" );
}
return transaction;
}
catch ( HibernateException e ) {View on GitHub (pinned to fad1729dce)
Solutions
- Move current-session access earlier, well before the transaction can complete
- Check the transaction status is STATUS_ACTIVE before calling getCurrentSession() and skip or fast-fail otherwise
- Find the earlier failure that marked the transaction rollback-only — that exception is the root cause, not this one
- For work that must run after completion, open a plain sessionFactory.openSession() with its own short transaction
Example fix
// before
public void afterCompletion() {
sessionFactory.getCurrentSession().persist(audit); // dying tx -> sync registration fails
}
// after
public void afterCompletion() {
try (Session s = sessionFactory.openSession()) {
s.beginTransaction();
s.persist(audit);
s.getTransaction().commit();
}
} Defensive patterns
Strategy: try-catch
Validate before calling
TransactionManager tm = platform.retrieveTransactionManager();
if (tm.getStatus() == jakarta.transaction.Status.STATUS_ACTIVE) {
Session s = sessionFactory.getCurrentSession(); // safe: sync registration will succeed
} Try / catch
try {
return sessionFactory.getCurrentSession();
} catch (org.hibernate.HibernateException e) {
if (e.getMessage().contains("register cleanup Synchronization")) {
// session was already closed by Hibernate; run the work in a fresh transaction instead of retrying
return runInNewTransaction(this::doWork);
}
throw e;
} Prevention
- Access current sessions only while the transaction is STATUS_ACTIVE
- Never call getCurrentSession() from completion callbacks or @PreDestroy
- Investigate rollback-only marks as root causes, not as noise to retry through
When it happens
Trigger: Calling getCurrentSession() when the JTA transaction is in a state that no longer accepts synchronizations: after it was marked rollback-only by an earlier failure, while it is preparing/completing, from afterCompletion-style callbacks, or when another component's synchronization registration poisoned the transaction.
Common situations: First DB access happening in the tail of a dying transaction (@PreDestroy, afterCompletion hooks, async handoff from a request thread); a previous exception marked the TX rollback-only but processing continued; transaction timeouts racing session access.
Related errors
- Could not obtain TransactionManager from JtaPlatform
- Unable to locate current JTA transaction
- Current transaction is not in progress
- Illegal attempt to specify a SynchronizationType when buildi
- Problem locating/validating JTA transaction
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/743a6e67d810092e.
Report an issue: GitHub.