hibernate/hibernate-orm · error · IllegalStateException
Transaction was not properly begun/started
Error message
Transaction was not properly begun/started
What it means
internalGetTransactionDriverControl() returns the TransactionDriver that drives the physical transaction; the field is populated lazily by begin()/isActive() when the session is open. The method exists (per its comment) to turn a confusing NullPointerException into a descriptive IllegalStateException when driver-dependent operations run before the transaction was begun.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionImpl.java:105
// 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" );
}
else {
return transactionDriverControl;
}
}
@Override
public void rollback() {
if ( !isActive() && jpaCompliance ) {
throw new IllegalStateException( "rollback() called on inactive transaction (in JPA compliant mode)" );
}
final var status = getStatus();
if ( status == TransactionStatus.ROLLED_BACK || status == TransactionStatus.NOT_ACTIVE ) {
// allow rollback() on completed transaction as noop
CORE_LOGGER.rollbackCalledOnInactiveTransaction();
}
else if ( !status.canRollback() ) {View on GitHub (pinned to fad1729dce)
Solutions
- Begin the transaction first: use session.beginTransaction() (begins immediately) before setTimeout() or other driver-dependent calls
- Check tx.isActive() before touching driver-backed operations
- Create the Transaction lazily, right before the work, rather than holding an un-begun reference across the request
Example fix
// before Transaction tx = session.getTransaction(); tx.setTimeout(30); // driver not created yet -> IllegalStateException tx.begin(); // after Transaction tx = session.beginTransaction(); // begin() creates the driver tx.setTimeout(30);
Defensive patterns
Strategy: validation
Validate before calling
if (!tx.isActive()) {
tx = session.beginTransaction();
}
tx.setTimeout(30); // driver exists only after begin Prevention
- Call session.beginTransaction() (which begins immediately) before driver-dependent calls like setTimeout()
- Treat an un-begun Transaction reference as unusable — only isActive() transactions expose driver features
When it happens
Trigger: Invoking any operation routed through the driver before begin(): commit()/rollback()/markRollbackOnly() paths on a never-begun Transaction, or a setTimeout()/similar call made on a Transaction object obtained but not started.
Common situations: Setting a transaction timeout before begin(); unit tests driving TransactionImpl directly without begin(); error handling that calls markRollbackOnly()/rollback() although begin() never ran.
Related errors
- Transaction timeout expired
- Transaction not successfully started
- Newer version [" + latestVersion + "] of entity [" + infoStr
- #buildNamedQueryRepository should not be called on InFlightM
- Named query hint [" + hintName + "] is not an integer: " + q
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/931aaac13167468e.
Report an issue: GitHub.