{"record":{"id":"ce0afd095cd11dd6","repo":"quarkusio/quarkus","slug":"transaction-is-not-active-consider-adding-transa","errorCode":null,"errorMessage":"Transaction is not active, consider adding @Transactional to your method to automatically activate one.","messagePattern":"Transaction is not active, consider adding @Transactional to your method to automatically activate one\\.","errorType":"exception","errorClass":"TransactionRequiredException","httpStatus":null,"severity":"error","filePath":"extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java","lineNumber":168,"sourceCode":"                case Status.STATUS_COMMITTING:\n                case Status.STATUS_MARKED_ROLLBACK:\n                case Status.STATUS_PREPARED:\n                case Status.STATUS_PREPARING:\n                    return true;\n                default:\n                    return false;\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    @Override\n    public void persist(Object entity) {\n        checkBlocking();\n        try (SessionResult emr = acquireSession()) {\n            if (!emr.allowModification) {\n                throw new TransactionRequiredException(TRANSACTION_IS_NOT_ACTIVE);\n            }\n            emr.session.persist(entity);\n        }\n    }\n\n    @Override\n    public <T> T merge(T entity) {\n        checkBlocking();\n        try (SessionResult emr = acquireSession()) {\n            if (!emr.allowModification) {\n                throw new TransactionRequiredException(TRANSACTION_IS_NOT_ACTIVE);\n            }\n            return emr.session.merge(entity);\n        }\n    }\n\n    @Override\n    public void remove(Object entity) {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java#L150-L186","documentation":"persist() in TransactionScopedSession first acquires a session; if the session was obtained only via the request-scoped fallback (emr.allowModification == false, meaning no transaction is active), Quarkus rejects the write with a JPA TransactionRequiredException. This mirrors the JPA spec: persist is a transactional operation and must run inside a transaction.","triggerScenarios":"Calling em.persist(entity) on the injected (transaction-scoped) EntityManager while quarkus.hibernate-orm.request-scoped.enabled=true and no @Transactional is active: a session is created in the request context, but since allowModification is false, persist throws TransactionRequiredException instead of silently doing nothing.","commonSituations":"Read endpoints that were extended to write without adding @Transactional; enabling request-scoped.enabled for read convenience and then assuming writes work; REST GET/POST handlers that call the EM directly; tests that exercise persist without a transaction.","solutions":["Add @Transactional to the method (or a service layer method) that calls persist so a transaction is active and allowModification is true.","Alternatively begin a transaction programmatically (UserTransaction.begin()/commit()) around the persist call.","Keep write operations out of request-scoped (read-only) code paths; route writes through a transactional bean.","If you expected this to fail earlier with ContextNotActiveException, note that enabling quarkus.hibernate-orm.request-scoped.enabled changes the failure mode to TransactionRequiredException on writes."],"exampleFix":"// before\n@ApplicationScoped\npublic class UserService {\n    @Inject EntityManager em;\n    public void register(User u) {\n        em.persist(u); // TransactionRequiredException\n    }\n}\n\n// after\n@ApplicationScoped\npublic class UserService {\n    @Inject EntityManager em;\n    @Transactional\n    public void register(User u) {\n        em.persist(u);\n    }\n}","handlingStrategy":"try-catch","validationCode":"boolean canPersistNow() {\n    return quarkusTx() != null && quarkusTx().isActive();\n    // or check request-scoped path allowModification indirectly:\n    // if request-scoped.enabled=true and no @Transactional, persist will throw\n}","typeGuard":null,"tryCatchPattern":"try {\n    em.persist(entity);\n} catch (TransactionRequiredException e) {\n    // no active transaction: re-run inside a transactional bean\n    txUserService.persist(entity);\n}","preventionTips":["Make @Transactional mandatory on any method that calls persist/merge/remove/flush/lock/refresh.","Remember request-scoped sessions are read-only for writes: writes always need a transaction.","Group writes in a service layer annotated at class level with @Transactional.","Write a test asserting writes fail loudly without @Transactional to catch regressions."],"tags":["hibernate-orm","jpa","transactions","persist"],"backgroundTag":"transaction-required","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}