{"record":{"id":"e167e8f254510b22","repo":"hibernate/hibernate-orm","slug":"jta-usertransaction-rollback-failed","errorCode":null,"errorMessage":"JTA UserTransaction.rollback() failed","messagePattern":"JTA UserTransaction\\.rollback\\(\\) failed","errorType":"exception","errorClass":"TransactionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionAdapterUserTransactionImpl.java","lineNumber":82,"sourceCode":"\t\t\tthrow new TransactionException( \"JTA UserTransaction.commit() failed\", e );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void rollback() {\n\t\ttry {\n\t\t\tif ( initiator ) {\n\t\t\t\tinitiator = false;\n\t\t\t\tJTA_LOGGER.callingUserTransactionRollback();\n\t\t\t\tuserTransaction.rollback();\n\t\t\t\tJTA_LOGGER.calledUserTransactionRollback();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmarkRollbackOnly();\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new TransactionException( \"JTA UserTransaction.rollback() failed\", e );\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic TransactionStatus getStatus() {\n\t\ttry {\n\t\t\tfinal var status = StatusTranslator.translate( userTransaction.getStatus() );\n\t\t\tif ( status == null ) {\n\t\t\t\tthrow new TransactionException( \"UserTransaction reported transaction status as unknown\" );\n\t\t\t}\n\t\t\treturn status;\n\t\t}\n\t\tcatch (SystemException e) {\n\t\t\tthrow new TransactionException( \"JTA UserTransaction.getStatus() failed\", e );\n\t\t}\n\t}\n","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/JtaTransactionAdapterUserTransactionImpl.java#L64-L100","documentation":"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.","triggerScenarios":"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.","commonSituations":"Timeout completing the transaction before the application's rollback call; bean-managed transactions rolled back from the wrong thread or context; TM under stress.","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"],"exampleFix":"// before\ntry { tx.commit(); }\ncatch (Exception e) { tx.rollback(); } // throws if tx already completed\n\n// after\ntry { tx.commit(); }\ncatch (Exception e) {\n    TransactionStatus st = tx.getStatus();\n    if ( st == TransactionStatus.ACTIVE || st == TransactionStatus.MARKED_ROLLBACK ) {\n        tx.rollback();\n    }\n    else {\n        log.debug(\"transaction already completed; nothing to roll back\", e);\n    }\n}","handlingStrategy":"validation","validationCode":"// Roll back only when the tx is still open\nTransactionStatus st = tx.getStatus();\nif ( st == TransactionStatus.ACTIVE || st == TransactionStatus.MARKED_ROLLBACK ) {\n    tx.rollback();\n}\nelse {\n    log.debug(\"transaction already completed; skipping rollback\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    tx.rollback();\n}\ncatch (TransactionException e) {\n    if ( e.getCause() instanceof SecurityException ) {\n        // caller not permitted to roll back this UT\n    }\n    else {\n        log.warn(\"rollback could not complete; tx may already be gone\", e);\n    }\n}","preventionTips":["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"],"tags":["jta","transactions","hibernate","usertransaction","rollback"],"backgroundTag":"transaction-rollback-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}