hibernate/hibernate-orm · error · IllegalStateException
Transaction not successfully started
Error message
Transaction not successfully started
What it means
TransactionImpl.commit() requires the transaction to be active (or at least marked rollback-only) so commit has something to drive. If the transaction was never begun — or already completed and not marked for rollback — the inactive state means there is nothing to commit, and Hibernate throws IllegalStateException('Transaction not successfully started') instead of performing a silent no-op.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionImpl.java:88
if ( jpaCompliance ) {
throw new IllegalStateException( "Transaction already active (in JPA compliant mode)" );
}
else if ( !transactionCoordinator.getTransactionCoordinatorBuilder().isJta() ) {
throw new IllegalStateException( "Resource-local transaction already active" );
}
}
else {
CORE_LOGGER.beginningTransaction();
transactionDriverControl.begin();
}
}
@Override
public void commit() {
// allow MARKED_ROLLBACK to propagate through to transactionDriverControl
if ( !isActive() ) {
// we have a transaction that is inactive and has not been marked for rollback only
throw new IllegalStateException( "Transaction not successfully started" );
}
else {
CORE_LOGGER.committingTransaction();
try {
internalGetTransactionDriverControl().commit();
}
catch (RuntimeException e) {
throw session.getExceptionConverter().convertCommitException( e );
}
}
}
@Nonnull
public TransactionDriver internalGetTransactionDriverControl() {
// NOTE here to help be a more descriptive NullPointerException
if ( transactionDriverControl == null ) {
throw new IllegalStateException( "Transaction was not properly begun/started" );
}View on GitHub (pinned to fad1729dce)
Solutions
- Guard the commit: if (tx.isActive()) { tx.commit(); } — or only commit in the path where you began it
- Structure try/finally so begin() happens before the try, and commit/rollback are mutually exclusive in finally
- On business exceptions call rollback() (or markRollbackOnly) instead of letting a commit be reached
Example fix
// before
Transaction tx = em.getTransaction();
try {
doWork();
} finally {
tx.commit(); // never begun / already done -> IllegalStateException
}
// after
Transaction tx = em.getTransaction();
tx.begin();
try {
doWork();
tx.commit();
} catch (RuntimeException e) {
if (tx.isActive()) {
tx.rollback();
}
throw e;
} Defensive patterns
Strategy: validation
Validate before calling
if (tx.isActive()) {
tx.commit();
} else {
log.warn("Skipping commit: transaction was never begun or already completed");
} Prevention
- Commit only on the path that began the transaction
- Track begun-state in a local variable or use try/finally with mutually exclusive commit/rollback
- Mark rollback-only instead of committing when prerequisites failed
When it happens
Trigger: tx.commit() without any tx.begin() (e.g. a Transaction reference obtained via em.getTransaction() but never begun); commit() after an earlier commit()/rollback() already completed the transaction; commit attempted when the driver control was never started.
Common situations: finally blocks that commit unconditionally even when begin() failed or was skipped; retry logic that commits twice; code paths where an exception happens before begin() but the catch/finally still commits; tests that forget begin().
Related errors
- Cannot begin Transaction on closed Session/EntityManager
- Transaction was not properly begun/started
- Unable to commit against JDBC Connection
- Newer version [" + latestVersion + "] of entity [" + infoStr
- The ClassLoaderService cannot be reused (this instance was s
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/dc341dcc74442f87.
Report an issue: GitHub.