flowable/flowable-engine · error · org.flowable.common.engine.api.FlowableException

SystemException while getting transaction

Error message

SystemException while getting transaction 

What it means

In JtaTransactionContext, getTransaction() calls TransactionManager.getTransaction() and translates any javax.transaction.SystemException into this FlowableException. It means the JTA transaction manager failed while resolving the transaction associated with the current thread, so Flowable cannot proceed with transactional work.

Solutions

  1. Inspect the wrapped cause for the transaction manager's failure details.
  2. Ensure Flowable commands run on threads managed by the JTA transaction manager (not raw executor threads without transaction context).
  3. Verify the TransactionManager bean/JNDI wiring passed into JtaTransactionContextFactory is the live container TM.
  4. If running standalone JTA (Bitronix/Atomikos/Narayana), confirm the TM is started before the engine executes commands.
  5. Retry the operation; persistent SystemException may require restarting the TM/service.

Example fix

// before: engine invoked from unmanaged thread
new Thread(() -> engine.getTaskService().complete(taskId)).start();
// after: execute within a managed transaction on the caller thread
userTransaction.begin();
try { engine.getTaskService().complete(taskId); userTransaction.commit(); }
catch (Exception e) { userTransaction.rollback(); throw e; }
Defensive patterns

Strategy: try-catch

Validate before calling

try {
  Transaction tx = tm.getTransaction();
  if (tx == null) throw new IllegalStateException("No JTA transaction on this thread");
} catch (SystemException e) {
  throw new IllegalStateException("TM failed to resolve transaction", e);
}

Type guard

boolean tmIsHealthy(TransactionManager tm) {
  try { tm.getTransaction(); return true; } catch (SystemException e) { return false; }
}

Try / catch

try {
  engine.getRuntimeService().startProcessInstanceByKey("p");
} catch (FlowableException e) {
  if (e.getMessage() != null && e.getMessage().contains("SystemException while getting transaction")) {
    // TM broken: escalate / retry after TM recovery
  } else throw e;
}

Prevention

When it happens

Trigger: Any JtaTransactionContext operation (e.g. rollback() or addTransactionListener() via getTransaction()) when TransactionManager.getTransaction() throws SystemException — TM internal failure, thread without proper TM association in an exotic setup.

Common situations: Improperly bootstrapped TransactionManager (e.g. standalone JTA like Atomikos/Narayana misconfigured); calling Flowable APIs from threads not managed by the TM; app-server TM service failures.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/5f7ec86dff91725c. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/cfg/jta/JtaTransactionContext.java:66

        // managed transaction, mark rollback-only if not done so already.
        try {
            Transaction transaction = getTransaction();
            int status = transaction.getStatus();
            if (status != Status.STATUS_NO_TRANSACTION && status != Status.STATUS_ROLLEDBACK) {
                transaction.setRollbackOnly();
            }
        } catch (IllegalStateException e) {
            throw new FlowableException("Unexpected IllegalStateException while marking transaction rollback only", e);
        } catch (SystemException e) {
            throw new FlowableException("SystemException while marking transaction rollback only", e);
        }
    }

    protected Transaction getTransaction() {
        try {
            return transactionManager.getTransaction();
        } catch (SystemException e) {
            throw new FlowableException("SystemException while getting transaction ", e);
        }
    }

    @Override
    public void addTransactionListener(TransactionState transactionState, final TransactionListener transactionListener) {

        Transaction transaction = getTransaction();
        CommandContext commandContext = Context.getCommandContext();
        try {
            transaction.registerSynchronization(new TransactionStateSynchronization(transactionState, transactionListener, commandContext));
        } catch (IllegalStateException e) {
            throw new FlowableException("IllegalStateException while registering synchronization ", e);
        } catch (RollbackException e) {
            throw new FlowableException("RollbackException while registering synchronization ", e);
        } catch (SystemException e) {
            throw new FlowableException("SystemException while registering synchronization ", e);
        }
    }

View on GitHub (pinned to d6d39ce1c6)