{"record":{"id":"a935019f65892764","repo":"hibernate/hibernate-orm","slug":"rollback-called-on-inactive-transaction-in-jpa","errorCode":null,"errorMessage":"rollback() called on inactive transaction (in JPA compliant mode)","messagePattern":"rollback\\(\\) called on inactive transaction \\(in JPA compliant mode\\)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionImpl.java","lineNumber":115,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n\n\t@Nonnull\n\tpublic TransactionDriver internalGetTransactionDriverControl() {\n\t\t// NOTE here to help be a more descriptive NullPointerException\n\t\tif ( transactionDriverControl == null ) {\n\t\t\tthrow new IllegalStateException( \"Transaction was not properly begun/started\" );\n\t\t}\n\t\telse {\n\t\t\treturn transactionDriverControl;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void rollback() {\n\t\tif ( !isActive() && jpaCompliance ) {\n\t\t\tthrow new IllegalStateException( \"rollback() called on inactive transaction (in JPA compliant mode)\" );\n\t\t}\n\n\t\tfinal var status = getStatus();\n\t\tif ( status == TransactionStatus.ROLLED_BACK || status == TransactionStatus.NOT_ACTIVE ) {\n\t\t\t// allow rollback() on completed transaction as noop\n\t\t\tCORE_LOGGER.rollbackCalledOnInactiveTransaction();\n\t\t}\n\t\telse if ( !status.canRollback() ) {\n\t\t\tthrow new TransactionException( \"Cannot roll back transaction in current status [\" + status.name() + \"]\" );\n\t\t}\n\t\telse if ( status != TransactionStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) {\n\t\t\tCORE_LOGGER.rollingBackTransaction();\n\t\t\tinternalGetTransactionDriverControl().rollback();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isActive() {","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionImpl.java#L97-L133","documentation":"TransactionImpl.rollback() starts with a JPA-compliance check: in JPA-compliant mode (hibernate.jpa.compliance.transaction=true), rolling back an inactive transaction is a spec violation and throws IllegalStateException. Native mode only logs rollbackCalledOnInactiveTransaction; in both modes rollback() on an already completed transaction (ROLLED_BACK/NOT_ACTIVE) is an allowed no-op.","triggerScenarios":"em.getTransaction().rollback() in a catch/finally block when the transaction was never begun or already completed, while the factory runs with JPA transaction compliance enabled.","commonSituations":"A catch-all rollback handler that runs even when begin() failed earlier; rollback attempted after commit() already finished; shared error-handling helpers applied to code paths that do not always start a transaction.","solutions":["Guard the handler: if (tx.isActive()) { tx.rollback(); }","Only roll back transactions your code path began; pair every begin() with exactly one commit-or-rollback","For lenient native semantics use markRollbackOnly(), which tolerates inactive transactions"],"exampleFix":"// before\ntry {\n    doWork();\n    tx.commit();\n} catch (RuntimeException e) {\n    tx.rollback(); // tx never begun or already done -> IllegalStateException in JPA mode\n}\n\n// after\ntry {\n    doWork();\n    tx.commit();\n} catch (RuntimeException e) {\n    if (tx.isActive()) {\n        tx.rollback();\n    }\n}","handlingStrategy":"validation","validationCode":"if (tx.isActive()) {\n    tx.rollback();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap rollback in isActive() guards in every catch/finally","Only roll back transactions your code path began","Use markRollbackOnly() when you need lenient, native-mode semantics"],"tags":["hibernate","transaction","rollback","jpa-compliance","inactive"],"backgroundTag":"rollback-inactive-transaction","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}