flowable/flowable-engine · error · org.flowable.common.engine.api.FlowableException
SystemException while marking transaction rollback only
Error message
SystemException while marking transaction rollback only
What it means
Flowable's JTA transaction context wraps Transaction.setRollbackOnly() and translates javax.transaction.SystemException into this FlowableException. SystemException indicates the transaction manager itself failed (a low-level, unexpected error in the JTA implementation) while trying to mark the transaction rollback-only.
Solutions
- Inspect the wrapped cause (getCause()) for the real transaction-manager failure and fix that underlying problem first.
- Verify the TransactionManager configuration: the JtaTransactionContextFactory must be wired to the app server's TransactionManager (correct JNDI name or managed bean).
- Upgrade/patch the application server or JTA implementation if the SystemException is a known TM bug.
- Check resource managers (datasources, JMS) for failures that propagate as SystemException during rollback.
- Retry the command in a fresh transaction; if the TM is degraded, restarting the server/container may be required.
Example fix
// before: custom TransactionManager lookup returning wrong instance
TransactionManager tm = (TransactionManager) ctx.lookup("java:comp/TransactionManager");
// after: use the container-provided manager appropriate to the server
TransactionManager tm = (TransactionManager) ctx.lookup("java:jboss/TransactionManager"); Defensive patterns
Strategy: try-catch
Validate before calling
try { tm.getTransaction(); } catch (SystemException e) {
throw new IllegalStateException("Transaction manager unhealthy: " + e.getMessage(), e);
} Try / catch
try {
runtimeService.startProcessInstanceByKey("p");
} catch (FlowableException e) {
if (e.getCause() instanceof SystemException) {
log.error("JTA TM failure", e.getCause());
// alert/retry; possibly restart TM
} else throw e;
} Prevention
- Verify TransactionManager wiring (JNDI name / managed bean) at startup with a smoke test.
- Monitor app-server transaction service health.
- Keep app server and JTA implementation patched for known SystemException bugs.
- Check datasources/resource adapters for failures that surface as SystemException.
When it happens
Trigger: Calling rollback() when the underlying TransactionManager/Transaction implementation throws SystemException from setRollbackOnly() — e.g. TM internals failure, corrupted transaction state, or resource manager errors surfaced as SystemException.
Common situations: Application server transaction service failures; misconfigured TransactionManager (wrong JNDI lookup / multiple TM instances); known bugs in older app server JTA implementations; resource adapter failures propagating SystemException.
Related errors
- SystemException while getting transaction
- IllegalStateException while registering synchronization
- RollbackException while registering synchronization
- SystemException while getting transaction
- SystemException while marking transaction rollback only
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/ccbb718a94f9b2f6.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/cfg/jta/JtaTransactionContext.java:58
@Override
public void commit() {
// managed transaction, ignore
}
@Override
public void rollback() {
// 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));View on GitHub (pinned to d6d39ce1c6)