quarkusio/quarkus · error · QuarkusTransactionException
Transaction already active
Error message
Transaction already active
What it means
RequestScopedTransaction.begin starts the request-scoped user transaction and throws QuarkusTransactionException('Transaction already active') if the underlying UserTransaction's status is not STATUS_NO_TRANSACTION, i.e. a transaction is already in progress on the thread. This guards the commit-on-request-scope-end contract against double begin.
Source
Thrown at extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/RequestScopedTransaction.java:57
TransactionManager transactionManager, TransactionManagerConfiguration transactionManagerConfiguration) {
this.userTransaction = userTransaction;
this.transactionManager = transactionManager;
this.transactionManagerConfiguration = transactionManagerConfiguration;
}
public RequestScopedTransaction() {
//for proxiability
this.userTransaction = null;
this.transactionManagerConfiguration = null;
this.transactionManager = null;
}
void begin(BeginOptions options) {
int timeout = options != null ? options.timeout : 0;
boolean commitOnRequestScopeEnd = options != null && options.commitOnRequestScopeEnd;
try {
if (userTransaction.getStatus() != Status.STATUS_NO_TRANSACTION) {
throw new QuarkusTransactionException("Transaction already active");
}
this.autoCommit = commitOnRequestScopeEnd;
if (timeout > 0) {
userTransaction.setTransactionTimeout(timeout);
}
userTransaction.begin();
createdTransaction = transactionManager.getTransaction();
} catch (NotSupportedException | SystemException e) {
throw new QuarkusTransactionException(e);
} finally {
if (timeout > 0) {
try {
userTransaction.setTransactionTimeout(
(int) transactionManagerConfiguration.defaultTransactionTimeout().toSeconds());
} catch (SystemException e) {
throw new QuarkusTransactionException(e);
}View on GitHub (pinned to e1c734241f)
Solutions
- Do not call QuarkusTransaction.begin when a transaction is already active — check QuarkusTransaction.isActive() first
- Ensure previous transactions are committed/rolled back (look for missing commit/rollback in error paths)
- Avoid mixing manual UserTransaction usage with request-scoped transaction management
- If a stale transaction leaks from earlier work, roll it back before beginning a new one
Example fix
// before
QuarkusTransaction.begin(); // may throw if already active
// after
if (!QuarkusTransaction.isActive()) {
QuarkusTransaction.begin();
} Defensive patterns
Strategy: try-catch
Validate before calling
try {
int status = userTransaction.getStatus();
if (status != Status.STATUS_NO_TRANSACTION) {
throw new IllegalStateException("Cannot begin: transaction status=" + status);
}
} catch (SystemException e) { /* handle */ } Try / catch
try {
QuarkusTransaction.begin();
} catch (QuarkusTransactionException e) {
if (e.getMessage().contains("Transaction already active")) {
QuarkusTransaction.rollback(); // or join existing tx instead
QuarkusTransaction.begin();
} else throw e;
} Prevention
- Check QuarkusTransaction.isActive() before beginning
- Always commit/rollback in finally blocks to avoid leaked transactions on worker threads
- Do not mix manual UserTransaction calls with request-scoped transaction management
- Watch for Narayana recovery/timeout reapers leaving transactions active
When it happens
Trigger: The request-scoped transaction bean's begin() is invoked twice in one request scope, or an external transaction (manual UserTransaction.begin, Narayana timeout recovery, or another component) was already started before the request-scoped transaction initializes.
Common situations: Mixing programmatic QuarkusTransaction.begin with the automatic request-scoped transaction management; a leaked/unclosed transaction from an earlier request handled by the same worker thread; nested service calls each triggering begin.
Related errors
- Cannot specify both an exception handler and SUSPEND_EXISTIN
- Transaction already active
- seconds cannot be negative
- Unknown semantics
- Error getting the status of the current transaction
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/fae3560f739f8504.
Report an issue: GitHub.