{"record":{"id":"c15af8210dd8909d","repo":"hibernate/hibernate-orm","slug":"could-not-access-jta-transaction-to-register-synch","errorCode":null,"errorMessage":"Could not access JTA Transaction to register synchronization","messagePattern":"Could not access JTA Transaction to register synchronization","errorType":"exception","errorClass":"JtaPlatformException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/AbstractJtaPlatform.java","lineNumber":54,"sourceCode":"\tprivate boolean cacheUserTransaction;\n\tprivate ServiceRegistryImplementor serviceRegistry;\n\n\tprivate final JtaSynchronizationStrategy tmSynchronizationStrategy = new TransactionManagerBasedSynchronizationStrategy();\n\n\t@Override\n\tpublic void injectServices(@Nonnull ServiceRegistryImplementor serviceRegistry) {\n\t\tthis.serviceRegistry = serviceRegistry;\n\t}\n\n\tprivate final class TransactionManagerBasedSynchronizationStrategy implements JtaSynchronizationStrategy {\n\n\t\t@Override\n\t\tpublic void registerSynchronization(Synchronization synchronization) {\n\t\t\ttry {\n\t\t\t\tgetTransactionManager().getTransaction().registerSynchronization( synchronization );\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tthrow new JtaPlatformException( \"Could not access JTA Transaction to register synchronization\", e );\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canRegisterSynchronization() {\n\t\t\treturn isActive( getTransactionManager() );\n\t\t}\n\t}\n\n\tprotected ServiceRegistry serviceRegistry() {\n\t\treturn serviceRegistry;\n\t}\n\n\tprotected JndiService jndiService() {\n\t\treturn serviceRegistry().requireService( JndiService.class );\n\t}\n\n\tprotected abstract TransactionManager locateTransactionManager();","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/internal/AbstractJtaPlatform.java#L36-L72","documentation":"Hibernate throws this JtaPlatformException from AbstractJtaPlatform.TransactionManagerBasedSynchronizationStrategy when it must attach a javax.transaction.Synchronization to the current JTA transaction, but getTransactionManager().getTransaction() throws, returns null, or returns a transaction that cannot accept registrations (already completed, rolled back, or marked rollback-only). It means Session work that needs transaction callbacks (flush, before-completion processing, second-level cache synchronization) ran without a usable JTA transaction.","triggerScenarios":"Session.flush()/auto-flush, beforeTransactionCompletion processing, or cache synchronization while no active JTA transaction exists; using the Session after ut.commit()/rollback(); the transaction is in STATUS_MARKED_ROLLBACK or a terminal state; hibernate.transaction.jta.platform configured for a runtime other than the one actually running so getTransactionManager() misbehaves.","commonSituations":"Spring/JTA apps where the platform property was copied from another server; code that keeps using a Session after the JTA transaction ended; upgrading the app server or Narayana so the previously configured TM no longer works; mixing RESOURCE_LOCAL persistence with leftover JTA platform settings.","solutions":["Ensure a JTA transaction is begun and still active before Session work: userTransaction.begin(), session operations, then commit()","Verify hibernate.transaction.jta.platform matches the runtime (JBossAppServerJtaPlatform on WildFly, NarayanaJtaPlatform standalone, etc.)","Audit code paths that touch the Session after transaction completion and move them inside the transaction boundary","If it appears after an upgrade, align hibernate-core and the transaction integration library versions"],"exampleFix":"// before: flush outside JTA transaction scope\nsession.flush(); // -> JtaPlatformException: could not access JTA transaction\n\n// after\nuserTransaction.begin();\ntry {\n    session.flush();\n    userTransaction.commit();\n}\ncatch (Exception e) {\n    userTransaction.rollback();\n}","handlingStrategy":"validation","validationCode":"// verify an active JTA transaction before Session work that registers synchronizations\nif (transactionManager.getStatus() != javax.transaction.Status.STATUS_ACTIVE) {\n    throw new IllegalStateException(\"JTA transaction not active (status=\" + transactionManager.getStatus() + \")\");\n}\nsession.flush();","typeGuard":null,"tryCatchPattern":"try {\n    session.flush();\n} catch (JtaPlatformException e) {\n    // no active JTA transaction, or it already completed\n    throw new IllegalStateException(\"Session work attempted outside an active JTA transaction\", e);\n}","preventionTips":["Begin the JTA transaction before Session operations in that unit of work","Set hibernate.transaction.jta.platform explicitly per deployment environment","Never reuse a Session after its JTA transaction committed or rolled back","Assert transaction status in integration tests before flushing"],"tags":["jta","transactions","synchronization","session-flush"],"backgroundTag":"jta-transaction-not-active","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}