hibernate/hibernate-orm · error · TransactionRequiredException

No active transaction

Error message

No active transaction

What it means

prepareForQueryExecution(requiresTxn=true) first checks the session is open and its transaction sync status, then demands an active transaction: requiresTxn && !isTransactionInProgress() throws TransactionRequiredException('No active transaction'). It is the guard for API paths that execute transactional work — notably procedure-call execution and other entry points flagged as requiring a transaction.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java:1148

		sessionUseProhibitedDepth--;
	}

	protected void checkSessionReentrancy() {
		if ( sessionUseProhibitedDepth > 0 ) {
			throw new IllegalStateException( "Session method called from entity lifecycle callback or Interceptor method" );
		}
	}

	protected void checksBeforeQueryCreation() {
		checkOpen();
		checkTransactionSyncStatus();
	}

	@Override
	public void prepareForQueryExecution(boolean requiresTxn) {
		checksBeforeQueryCreation();
		if ( requiresTxn && !isTransactionInProgress() ) {
			throw new TransactionRequiredException( "No active transaction" );
		}
	}

	@Override
	@Nullable
	public Timeout getDefaultTimeout() {
		final var timeoutInMilliseconds = getHintedQueryTimeout();
		return timeoutInMilliseconds != null
				? Timeouts.interpretMilliSeconds( timeoutInMilliseconds )
				: null;
	}

	protected Integer getHintedQueryTimeout() {
		return LegacySpecHelper.getInteger(
				HINT_SPEC_QUERY_TIMEOUT,
				HINT_JAVAEE_QUERY_TIMEOUT,
				this::getSessionProperty
		);

View on GitHub (pinned to fad1729dce)

Solutions

  1. Wrap the operation in a transaction: session.beginTransaction() ... commit(), or @Transactional on the method.
  2. In Spring, verify the call crosses the proxy boundary (public method on another bean), not self-invocation.
  3. In tests, annotate the test/method @Transactional (Spring test framework) or use TransactionTemplate.

Example fix

// before
StoredProcedureQuery q = em.createStoredProcedureQuery("recalc_totals");
q.execute(); // TransactionRequiredException: No active transaction
// after
em.getTransaction().begin();
try {
    q.execute();
    em.getTransaction().commit();
} catch (RuntimeException e) {
    em.getTransaction().rollback();
    throw e;
}
Defensive patterns

Strategy: validation

Validate before calling

if (!session.isTransactionInProgress()) {
    session.beginTransaction();
}
StoredProcedureQuery q = em.createStoredProcedureQuery("recalc_totals");
q.execute();

Try / catch

try {
    q.execute();
} catch (TransactionRequiredException e) {
    // only retry when caller forgot the tx; never mask business failures
    session.beginTransaction();
    q.execute();
    session.getTransaction().commit();
}

Prevention

When it happens

Trigger: Creating/executing a transaction-requiring query path without a transaction: StoredProcedureQuery execution and internal query preparation paths that pass requiresTxn=true, invoked outside beginTransaction()/@Transactional, or on a JTA thread whose transaction never started.

Common situations: Calling stored-procedure DML from a non-transactional method; plain Java SE usage where beginTransaction() was dropped in a refactor; Spring self-invocation bypassing the @Transactional proxy; test code calling query APIs directly without a transactional test (missing @Transactional on the test class).

Related errors


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