hibernate/hibernate-orm · error · TransactionException
JTA TransactionManager.rollback() failed
Error message
JTA TransactionManager.rollback() failed
What it means
TransactionManager.rollback() threw while executing Transaction.rollback(); wrapped causes are usually SystemException or IllegalStateException, for example when the transaction already completed (a TM timeout finished it, or the container rolled it back) or rollback is invoked from a non-owner thread. Hibernate only calls rollback when it was the initiator - otherwise it marks rollback-only. This exception says the explicit rollback could not complete; the original business error, if any, is separate.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionAdapterTransactionManagerImpl.java:81
throw new TransactionException( "JTA TransactionManager.commit() failed", e );
}
}
@Override
public void rollback() {
try {
if ( initiator ) {
initiator = false;
JTA_LOGGER.callingTransactionManagerRollback();
transactionManager.rollback();
JTA_LOGGER.calledTransactionManagerRollback();
}
else {
markRollbackOnly();
}
}
catch (Exception e) {
throw new TransactionException( "JTA TransactionManager.rollback() failed", e );
}
}
@Override
@Nonnull
public TransactionStatus getStatus() {
try {
final var status = StatusTranslator.translate( transactionManager.getStatus() );
if ( status == null ) {
throw new TransactionException( "TransactionManager reported transaction status as unknown" );
}
return status;
}
catch (SystemException e) {
throw new TransactionException( "JTA TransactionManager#getStatus failed", e );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Check tx.getStatus() before rolling back and skip when the transaction is already completed
- Increase the JTA transaction timeout if transactions complete before the rollback call
- Keep begin, commit and rollback on the same thread
- If SystemException persists, check TransactionManager health and logs
Example fix
// before
try { tx.commit(); }
catch (Exception e) { tx.rollback(); } // may throw if tx already completed
// after
try { tx.commit(); }
catch (Exception e) {
TransactionStatus st = tx.getStatus();
if ( st == TransactionStatus.ACTIVE || st == TransactionStatus.MARKED_ROLLBACK ) {
tx.rollback();
}
else {
log.debug("transaction already completed; nothing to roll back", e);
}
} Defensive patterns
Strategy: validation
Validate before calling
// Roll back only when the tx is still open
TransactionStatus st = tx.getStatus();
if ( st == TransactionStatus.ACTIVE || st == TransactionStatus.MARKED_ROLLBACK ) {
tx.rollback();
}
else {
log.debug("transaction already completed; skipping rollback");
} Try / catch
try {
tx.rollback();
}
catch (TransactionException e) {
if ( e.getCause() instanceof IllegalStateException || e.getCause() instanceof SystemException ) {
log.warn("rollback could not complete; tx may already be gone", e);
}
} Prevention
- Check Transaction.getStatus() before rollback
- Set JTA timeouts long enough that transactions do not complete underneath the application
- Keep begin/commit/rollback on one thread
When it happens
Trigger: tx.rollback() after the JTA transaction already finished (timeout fired between the failure and the rollback call, container completed it); rollback invoked from a different thread; TM internal error.
Common situations: JTA timeout completing the transaction underneath the application; asynchronous processing moving transaction work across threads; TM in recovery.
Related errors
- JTA UserTransaction.rollback() failed
- Current transaction is not in progress
- Transaction is not accessible when using JTA with JPA-compli
- Exception pulsing TransactionCoordinator
- Explicitly joining a JTA transaction requires a JTA transact
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e3ef4667c0a02859.
Report an issue: GitHub.