Activiti/Activiti · error · TransactionException

Unable to commit transaction

Error message

Unable to commit transaction

What it means

doCommit() commits the newly started transaction with TransactionManager.commit(). HeuristicMixedException, HeuristicRollbackException, RollbackException, or SystemException all indicate the commit did not complete cleanly; each is wrapped in this TransactionException.

Solutions

  1. Look at the wrapped cause: RollbackException usually means rollback-only was set — find and remove the swallowed resource error
  2. Check XA resource logs for heuristic outcomes and resolve heuristics per the transaction manager's recovery tools
  3. Increase transaction timeouts if long commands exceed the default JTA timeout

Example fix

// before
try { someOperation(); } catch (Exception e) { log.warn(...); } // tx marked rollback-only silently
// after
try { someOperation(); } catch (Exception e) { throw new ActivitiException("operation failed", e); }
Defensive patterns

Strategy: try-catch

Try / catch

try { engine.execute(cmd); } catch (TransactionException e) { Throwable c = e.getCause(); if (c instanceof RollbackException) { /* find rollback-only source */ } else { /* heuristic/system: consult TM recovery */ } }

Prevention

When it happens

Trigger: execute() calls doCommit() after the command succeeds and transactionManager.commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException (e.g. marked rollback-only), or SystemException.

Common situations: A resource marked the transaction rollback-only during the command (e.g. DB constraint violation swallowed by application code); two-phase commit heuristic outcomes after resource failures; transaction timed out before commit.

Related errors


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

Appendix: source

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

    }

    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();
        } catch (HeuristicMixedException e) {
            throw new TransactionException("Unable to commit transaction", e);
        } catch (HeuristicRollbackException e) {
            throw new TransactionException("Unable to commit transaction", e);
        } catch (RollbackException e) {
            throw new TransactionException("Unable to commit transaction", e);
        } catch (SystemException e) {
            throw new TransactionException("Unable to commit transaction", e);
        } catch (RuntimeException e) {
            doRollback(true, e);
            throw e;
        } catch (Error e) {
            doRollback(true, e);
            throw e;
        }
    }

    private void doRollback(boolean isNew, Throwable originalException) {
        Throwable rollbackEx = null;
        try {

View on GitHub (pinned to 56435b1a97)