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

SystemException while registering synchronization

Error message

SystemException while registering synchronization 

What it means

Flowable wraps the JTA TransactionManager's registerSynchronization() failures into a FlowableException. A SystemException from the underlying transaction manager signals that the transaction service itself failed unexpectedly (internal transaction manager error, wrongly configured TM, or no active transaction support). Flowable rethrows it so the command fails and the engine can roll back cleanly.

Solutions

  1. Inspect the cause chain (getCause()) for the underlying SystemException message from the JTA transaction manager and fix the TM configuration
  2. Verify the JTA TransactionManager is properly initialized and accessible before starting commands (e.g. Atomikos/Narayana startup logs)
  3. Ensure a transaction is actually active when the command runs; do not invoke engine commands outside a JTA transaction in JTA mode
  4. Check for javax.transaction vs jakarta.transaction duplication on the classpath (Flowable version mismatch with app server)
  5. Enable debug logging on org.flowable.common.engine.impl.cfg.jta to see the exact failing transaction state

Example fix

// before: engine in JTA mode but no TM registered
cfg.setTransactionManager(null);
// after
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
cfg.setTransactionManager(tm);
Defensive patterns

Strategy: try-catch

Validate before calling

// before executing commands in JTA mode
try {
    jakarta.transaction.Transaction tx = transactionManager.getTransaction();
    if (tx == null) throw new IllegalStateException("No active JTA transaction");
} catch (SystemException e) {
    throw new IllegalStateException("Transaction manager unhealthy: " + e.getMessage(), e);
}

Try / catch

try {
    flowableCommand.execute(...);
} catch (FlowableException e) {
    if (e.getMessage().contains("SystemException while registering synchronization")) {
        // inspect e.getCause(); mark transaction rollback-only or fail request
        transactionManager.setRollbackOnly();
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling addTransactionListener to register a TransactionStateSynchronization when the JTA transaction manager is in a broken/failed state; registerSynchronization() on jakarta/javax.transaction.Transaction throws SystemException.

Common situations: Misconfigured JTA transaction manager (e.g. Atomikos/Narayana/Bitronix failing to boot), using the engine outside a proper JTA environment, transaction already marked rollback-only or TM internal failure, classpath mixing javax and jakarta transaction APIs.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

            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);
        }
    }

    public static class TransactionStateSynchronization implements Synchronization {

        protected final TransactionListener transactionListener;
        protected final TransactionState transactionState;
        private final CommandContext commandContext;

        public TransactionStateSynchronization(TransactionState transactionState, TransactionListener transactionListener, CommandContext commandContext) {
            this.transactionState = transactionState;
            this.transactionListener = transactionListener;
            this.commandContext = commandContext;
        }

        @Override
        public void beforeCompletion() {
            if (TransactionState.COMMITTING == transactionState || TransactionState.ROLLINGBACK == transactionState) {

View on GitHub (pinned to d6d39ce1c6)