{"record":{"id":"03bedda30eb700e0","repo":"quarkusio/quarkus","slug":"transaction-already-active","errorCode":null,"errorMessage":"Transaction already active","messagePattern":"Transaction already active","errorType":"exception","errorClass":"QuarkusTransactionException","httpStatus":null,"severity":"error","filePath":"extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/QuarkusTransactionImpl.java","lineNumber":94,"sourceCode":"        if (isTransactionActive()) {\n            return callInTheirTx(options, task);\n        } else {\n            return callInOurTx(options, task);\n        }\n    }\n\n    private static boolean isTransactionActive() {\n        try {\n            int status = getUserTransaction().getStatus();\n            return status != Status.STATUS_NO_TRANSACTION;\n        } catch (SystemException e) {\n            throw new QuarkusTransactionException(e);\n        }\n    }\n\n    private static <T> T callDisallowExisting(RunOptionsBase options, Callable<T> task) {\n        if (isTransactionActive()) {\n            throw new QuarkusTransactionException(new IllegalStateException(\"Transaction already active\"));\n        }\n        return callInOurTx(options, task);\n    }\n\n    private static <T> T callRequireNew(RunOptionsBase options, Callable<T> task) {\n        TransactionManager transactionManager = getTransactionManager();\n        Transaction transaction = null;\n        try {\n            if (isTransactionActive()) {\n                transaction = transactionManager.suspend();\n            }\n            T result = callInOurTx(options, task);\n            if (transaction != null) {\n                try {\n                    transactionManager.resume(transaction);\n                    transaction = null;\n                } catch (Exception e) {\n                    throw new QuarkusTransactionException(e);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/QuarkusTransactionImpl.java#L76-L112","documentation":"callDisallowExisting implements TransactionSemantics.DISALLOW_EXISTING: if a transaction is already active on the current thread it wraps an IllegalStateException('Transaction already active') in QuarkusTransactionException. DISALLOW_EXISTING requires no active transaction when the task begins.","triggerScenarios":"Calling QuarkusTransaction.call/run with DISALLOW_EXISTING semantics from within code that already started a transaction (another QuarkusTransaction call, @Transactional method, or manual UserTransaction.begin).","commonSituations":"Nesting programmatic transactions with DISALLOW_EXISTING inside @Transactional service methods; transaction interceptor still active on the call path (e.g. CDI interceptor not suspended).","solutions":["Remove the outer transaction so the thread has no active tx (use NOT_SUPPORTED or restructure code)","Change semantics to REQUIRED or REQUIRES_NEW if nesting is intended","Catch QuarkusTransactionException if the 'no active tx' precondition can legitimately be violated"],"exampleFix":"// before\nQuarkusTransaction.call(new RunOptions().semantics(TransactionSemantics.DISALLOW_EXISTING), task); // inside @Transactional method\n// after\nQuarkusTransaction.call(new RunOptions().semantics(TransactionSemantics.REQUIRES_NEW), task);","handlingStrategy":"try-catch","validationCode":"if (QuarkusTransaction.isActive() && semantics == TransactionSemantics.DISALLOW_EXISTING) {\n    throw new IllegalStateException(\"Cannot use DISALLOW_EXISTING inside an active transaction\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return QuarkusTransaction.call(new RunOptions().semantics(TransactionSemantics.DISALLOW_EXISTING), task);\n} catch (QuarkusTransactionException e) {\n    if (e.getCause() instanceof IllegalStateException && e.getCause().getMessage().contains(\"Transaction already active\")) {\n        return runWithoutTransaction(task); // or restructure caller\n    }\n    throw e;\n}","preventionTips":["Call QuarkusTransaction.isActive() before DISALLOW_EXISTING blocks","Avoid wrapping @Transactional methods with DISALLOW_EXISTING programmatic calls","Map transactional boundaries explicitly in the service layer"],"tags":["narayana","transaction","illegal-state","nested-transaction"],"backgroundTag":"transaction-already-active","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}