hibernate/hibernate-orm · error · TransactionException
JTA UserTransaction.rollback() failed
Error message
JTA UserTransaction.rollback() failed
What it means
UserTransaction.rollback() threw while executing Transaction.rollback(); Hibernate only calls it when it initiated the transaction via the UT, otherwise it marks rollback-only. The wrapped exception (SystemException, IllegalStateException, SecurityException) means the explicit rollback could not complete - e.g., the transaction already ended via timeout, or the caller is not permitted to roll it back. The original business failure, if any, is a separate exception.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionAdapterUserTransactionImpl.java:82
throw new TransactionException( "JTA UserTransaction.commit() failed", e );
}
}
@Override
public void rollback() {
try {
if ( initiator ) {
initiator = false;
JTA_LOGGER.callingUserTransactionRollback();
userTransaction.rollback();
JTA_LOGGER.calledUserTransactionRollback();
}
else {
markRollbackOnly();
}
}
catch (Exception e) {
throw new TransactionException( "JTA UserTransaction.rollback() failed", e );
}
}
@Override
@Nonnull
public TransactionStatus getStatus() {
try {
final var status = StatusTranslator.translate( userTransaction.getStatus() );
if ( status == null ) {
throw new TransactionException( "UserTransaction reported transaction status as unknown" );
}
return status;
}
catch (SystemException e) {
throw new TransactionException( "JTA UserTransaction.getStatus() failed", e );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Check tx.getStatus() before rollback; if it is neither ACTIVE nor MARKED_ROLLBACK, skip and log
- Raise the JTA timeout if transactions end prematurely
- Ensure rollback happens in the same context/thread that began the transaction
- Investigate persistent SystemException causes via TM logs
Example fix
// before
try { tx.commit(); }
catch (Exception e) { tx.rollback(); } // throws 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 SecurityException ) {
// caller not permitted to roll back this UT
}
else {
log.warn("rollback could not complete; tx may already be gone", e);
}
} Prevention
- Check status before rollback; skip when already completed
- Keep BMT rollback in the same context/thread that began the transaction
- Align application and JTA timeouts
When it happens
Trigger: tx.rollback() when the JTA transaction already completed (UT/TM timeout finished it, container completed it), rollback from a context without permission, or a UT internal error.
Common situations: Timeout completing the transaction before the application's rollback call; bean-managed transactions rolled back from the wrong thread or context; TM under stress.
Related errors
- JTA TransactionManager.rollback() failed
- JTA UserTransaction.begin() failed
- JTA UserTransaction.commit() failed
- UserTransaction reported transaction status as unknown
- JTA UserTransaction.getStatus() failed
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e167e8f254510b22.
Report an issue: GitHub.