hibernate/hibernate-orm · error · HibernateException

Current transaction is not in progress

Error message

Current transaction is not in progress

What it means

A JTA Transaction object was found but its status is not active (for example STATUS_MARKED_ROLLBACK, STATUS_PREPARING or STATUS_COMMITTED). Hibernate deliberately refuses to bind a session to a transaction it may never get a completion callback for — the map entry would leak — and throws instead, as noted in the source comment.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/context/internal/JTASessionContext.java:108

			}
			catch ( Throwable e ) {
				CURRENT_SESSION_LOGGER.unableToReleaseGeneratedCurrentSessionOnFailedSynchronizationRegistration(e);
			}
			throw new HibernateException( "Unable to register cleanup Synchronization with TransactionManager" );
		}
	}

	private static @Nonnull Transaction getTransaction(TransactionManager transactionManager) {
		try {
			final var transaction = transactionManager.getTransaction();
			if ( transaction == null ) {
				throw new HibernateException( "Unable to locate current JTA transaction" );
			}
			if ( !isActive( transaction.getStatus() ) ) {
				// We could register the session against the transaction even though it is
				// not started, but we'd have no guarantee of ever getting the map
				// entries cleaned up (aside from spawning threads).
				throw new HibernateException( "Current transaction is not in progress" );
			}
			return transaction;
		}
		catch ( HibernateException e ) {
			throw e;
		}
		catch ( Throwable t ) {
			throw new HibernateException( "Problem locating/validating JTA transaction", t );
		}
	}

	/**
	 * Builds a {@link CleanupSync} capable of cleaning up the current session map as an after transaction
	 * callback.
	 *
	 * @param transactionIdentifier The transaction identifier under which the current session is registered.
	 * @return The cleanup synch.
	 */

View on GitHub (pinned to fad1729dce)

Solutions

  1. Start a fresh transaction for the new work — the marked/completing one cannot be joined
  2. Locate and log the original failure that marked the transaction rollback-only
  3. Guard session access with a status check (STATUS_ACTIVE) and route non-active cases to a new transaction
  4. Move post-failure work (audit, notifications, compensation) into REQUIRES_NEW or a separate resource

Example fix

// before
catch (Exception e) { log.error(e); } // tx silently marked rollback-only
...same request...
sessionFactory.getCurrentSession().persist(audit); // throws

// after
catch (Exception e) {
    log.error(e);
    auditService.recordInNewTransaction(event); // REQUIRES_NEW
}
Defensive patterns

Strategy: validation

Validate before calling

int status = transactionManager.getStatus();
if (status != jakarta.transaction.Status.STATUS_ACTIVE) {
    throw new IllegalStateException("Transaction not active (status " + status + "); start a new transaction before accessing the current session");
}
Session s = sessionFactory.getCurrentSession();

Try / catch

try {
    return sessionFactory.getCurrentSession();
} catch (org.hibernate.HibernateException e) {
    if (e.getMessage().contains("not in progress")) {
        // the bound transaction is marked rollback/completing; new work needs a fresh transaction
        return runInNewTransaction(this::doWork);
    }
    throw e;
}

Prevention

When it happens

Trigger: getCurrentSession() after the transaction was marked rollback-only by a prior exception (constraint violation in another EJB, rollback-only resource), or while the transaction is mid-completion; retry code re-entering the same request after a failure.

Common situations: Catch-and-continue error handling that stays inside a poisoned transaction; @Transactional(REQUIRED) methods reusing a marked-rollback transaction after a caught exception; timers/async tasks outliving their originating transaction.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/4a1ffa020f22c6a1. Report an issue: GitHub.