{"record":{"id":"4a1ffa020f22c6a1","repo":"hibernate/hibernate-orm","slug":"current-transaction-is-not-in-progress","errorCode":null,"errorMessage":"Current transaction is not in progress","messagePattern":"Current transaction is not in progress","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/context/internal/JTASessionContext.java","lineNumber":108,"sourceCode":"\t\t\t}\n\t\t\tcatch ( Throwable e ) {\n\t\t\t\tCURRENT_SESSION_LOGGER.unableToReleaseGeneratedCurrentSessionOnFailedSynchronizationRegistration(e);\n\t\t\t}\n\t\t\tthrow new HibernateException( \"Unable to register cleanup Synchronization with TransactionManager\" );\n\t\t}\n\t}\n\n\tprivate static @Nonnull Transaction getTransaction(TransactionManager transactionManager) {\n\t\ttry {\n\t\t\tfinal var transaction = transactionManager.getTransaction();\n\t\t\tif ( transaction == null ) {\n\t\t\t\tthrow new HibernateException( \"Unable to locate current JTA transaction\" );\n\t\t\t}\n\t\t\tif ( !isActive( transaction.getStatus() ) ) {\n\t\t\t\t// We could register the session against the transaction even though it is\n\t\t\t\t// not started, but we'd have no guarantee of ever getting the map\n\t\t\t\t// entries cleaned up (aside from spawning threads).\n\t\t\t\tthrow new HibernateException( \"Current transaction is not in progress\" );\n\t\t\t}\n\t\t\treturn transaction;\n\t\t}\n\t\tcatch ( HibernateException e ) {\n\t\t\tthrow e;\n\t\t}\n\t\tcatch ( Throwable t ) {\n\t\t\tthrow new HibernateException( \"Problem locating/validating JTA transaction\", t );\n\t\t}\n\t}\n\n\t/**\n\t * Builds a {@link CleanupSync} capable of cleaning up the current session map as an after transaction\n\t * callback.\n\t *\n\t * @param transactionIdentifier The transaction identifier under which the current session is registered.\n\t * @return The cleanup synch.\n\t */","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/context/internal/JTASessionContext.java#L90-L126","documentation":"A JTA Transaction object was found but its status is not active (for example STATUS_MARKED_ROLLBACK, STATUS_PREPARING or STATUS_COMMITTED). Hibernate deliberately refuses to bind a session to a transaction it may never get a completion callback for — the map entry would leak — and throws instead, as noted in the source comment.","triggerScenarios":"getCurrentSession() after the transaction was marked rollback-only by a prior exception (constraint violation in another EJB, rollback-only resource), or while the transaction is mid-completion; retry code re-entering the same request after a failure.","commonSituations":"Catch-and-continue error handling that stays inside a poisoned transaction; @Transactional(REQUIRED) methods reusing a marked-rollback transaction after a caught exception; timers/async tasks outliving their originating transaction.","solutions":["Start a fresh transaction for the new work — the marked/completing one cannot be joined","Locate and log the original failure that marked the transaction rollback-only","Guard session access with a status check (STATUS_ACTIVE) and route non-active cases to a new transaction","Move post-failure work (audit, notifications, compensation) into REQUIRES_NEW or a separate resource"],"exampleFix":"// before\ncatch (Exception e) { log.error(e); } // tx silently marked rollback-only\n...same request...\nsessionFactory.getCurrentSession().persist(audit); // throws\n\n// after\ncatch (Exception e) {\n    log.error(e);\n    auditService.recordInNewTransaction(event); // REQUIRES_NEW\n}","handlingStrategy":"validation","validationCode":"int status = transactionManager.getStatus();\nif (status != jakarta.transaction.Status.STATUS_ACTIVE) {\n    throw new IllegalStateException(\"Transaction not active (status \" + status + \"); start a new transaction before accessing the current session\");\n}\nSession s = sessionFactory.getCurrentSession();","typeGuard":null,"tryCatchPattern":"try {\n    return sessionFactory.getCurrentSession();\n} catch (org.hibernate.HibernateException e) {\n    if (e.getMessage().contains(\"not in progress\")) {\n        // the bound transaction is marked rollback/completing; new work needs a fresh transaction\n        return runInNewTransaction(this::doWork);\n    }\n    throw e;\n}","preventionTips":["Never continue processing inside a marked-rollback transaction","Move post-failure work to REQUIRES_NEW or a separate resource","Log transaction status before session access when debugging lifecycle races"],"tags":["hibernate","jta","transaction-status","rollback","current-session"],"backgroundTag":"transaction-not-active","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}