Activiti/Activiti · error · TransactionException

Unable to suspend transaction

Error message

Unable to suspend transaction

What it means

Before running the command inside a new transaction, the interceptor suspends any existing transaction via TransactionManager.suspend(). A SystemException means the transaction manager failed to detach the current transaction from the thread; it is wrapped in a TransactionException.

Solutions

  1. Do not invoke the engine inside a transaction context that cannot be suspended, or configure the engine to join rather than require new transactions
  2. Verify JTA provider compatibility (e.g. Atomikos/Narayana versions) with Activiti's JTA interceptor
  3. Inspect the SystemException cause to identify the illegal transaction state
Defensive patterns

Strategy: validation

Validate before calling

if (tm.getStatus() != Status.STATUS_NO_TRANSACTION) { /* decide: join or explicitly suspend, do not rely on implicit suspend */ }

Try / catch

try { engine.execute(cmd); } catch (TransactionException e) { if (e.getCause() instanceof SystemException && insideSuspension(e)) { /* restructure to avoid suspend */ } }

Prevention

When it happens

Trigger: execute() calls doSuspend() and transactionManager.suspend() throws SystemException, e.g. the thread's transaction is in an illegal state for suspension.

Common situations: Calling engine commands while a container-managed transaction is active where suspension is disallowed; transaction manager bugs or incompatible JTA implementations.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/41773c02d40b5093. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/JtaTransactionInterceptor.java:107

            throw new TransactionException("Unable to begin transaction", e);
        } catch (SystemException e) {
            throw new TransactionException("Unable to begin transaction", e);
        }
    }

    private boolean isExisting() {
        try {
            return transactionManager.getStatus() != Status.STATUS_NO_TRANSACTION;
        } catch (SystemException e) {
            throw new TransactionException("Unable to retrieve transaction status", e);
        }
    }

    private Transaction doSuspend() {
        try {
            return transactionManager.suspend();
        } catch (SystemException e) {
            throw new TransactionException("Unable to suspend transaction", e);
        }
    }

    private void doResume(Transaction tx) {
        if (tx != null) {
            try {
                transactionManager.resume(tx);
            } catch (SystemException e) {
                throw new TransactionException("Unable to resume transaction", e);
            } catch (InvalidTransactionException e) {
                throw new TransactionException("Unable to resume transaction", e);
            }
        }
    }

    private void doCommit() {
        try {
            transactionManager.commit();

View on GitHub (pinned to 56435b1a97)