hibernate/hibernate-orm · error · IllegalStateException
Cannot begin Transaction on closed Session/EntityManager
Error message
Cannot begin Transaction on closed Session/EntityManager
What it means
TransactionImpl.begin() first checks session.isOpen(); a closed Session/EntityManager can no longer coordinate a physical transaction, so begin() throws IllegalStateException instead of resurrecting it. This mirrors the JPA rule that a closed EntityManager is unusable.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionImpl.java:61
.isJpaTransactionComplianceEnabled();
if ( session.isOpen() && transactionCoordinator.isActive() ) {
transactionDriverControl =
transactionCoordinator.getTransactionDriverControl();
}
else {
CORE_LOGGER.transactionCreatedOnClosedSession();
}
if ( CORE_LOGGER.isDebugEnabled() && jpaCompliance ) {
CORE_LOGGER.transactionCreatedInJpaCompliantMode();
}
}
@Override
public void begin() {
if ( !session.isOpen() ) {
throw new IllegalStateException( "Cannot begin Transaction on closed Session/EntityManager" );
}
if ( transactionDriverControl == null ) {
transactionDriverControl =
transactionCoordinator.getTransactionDriverControl();
}
if ( isActive() ) {
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();View on GitHub (pinned to fad1729dce)
Solutions
- Get a fresh EntityManager/Session from the factory instead of reusing the closed instance
- Check session.isOpen() before begin() and reopen or fail with a clear message when closed
- Fix lifecycle ownership: the component that begins the transaction should also own (and close) the session
Example fix
// before
EntityManager em = cachedEm; // may already be closed
em.getTransaction().begin(); // IllegalStateException
// after
if (!em.isOpen()) {
em = emf.createEntityManager();
}
em.getTransaction().begin(); Defensive patterns
Strategy: validation
Validate before calling
if (!session.isOpen()) {
session = sessionFactory.openSession(); // or emf.createEntityManager()
}
session.beginTransaction(); Try / catch
try {
em.getTransaction().begin();
} catch (IllegalStateException e) {
if (String.valueOf(e.getMessage()).contains("closed Session")) {
em = emf.createEntityManager();
em.getTransaction().begin();
} else {
throw e;
}
} Prevention
- Never cache EntityManager/Session in long-lived fields; create per unit of work
- Check isOpen() at hand-off boundaries (e.g. receiving an EM from a filter)
- Keep session ownership single-threaded and single-owner
When it happens
Trigger: em.getTransaction().begin() or session.beginTransaction() after em.close()/session.close(); the same call on a session closed by a container filter (Open EntityManager in View), an earlier exception, or another thread sharing the session.
Common situations: An EntityManager cached in a field, HttpSession attribute, or singleton bean reused after the owning request closed it; closing order bugs in @PreDestroy or try-with-resources; tests that close the EM in setup but keep using it; a shared session accessed concurrently so one thread closes it mid-use.
Related errors
- Transaction not successfully started
- Session/EntityManager is closed
- Newer version [" + latestVersion + "] of entity [" + infoStr
- The ClassLoaderService cannot be reused (this instance was s
- No child ServiceRegistry registrations found
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1c10e2ad9fcb516b.
Report an issue: GitHub.