quarkusio/quarkus · error · ContextNotActiveException

Cannot use the StatelessSession because neither a transactio

Error message

Cannot use the StatelessSession because neither a transaction nor a CDI request context is active. Consider adding @Transactional to your method to automatically activate a transaction, or @ActivateRequestContext if you have valid reasons not to use transactions.

What it means

TransactionScopedStatelessSession.acquireSession() resolves a StatelessSession either from an active JTA transaction or, when request-scoped sessions are enabled (quarkus.hibernate-orm.request-scoped.enabled=true), from an active CDI request context. When both are missing and request-scoped mode is enabled, it throws ContextNotActiveException telling you no usable scope exists. Called by refresh and all createQuery/createNamedQuery/createNativeQuery/stored-procedure methods.

Source

Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedStatelessSession.java:92

    SessionResult acquireSession() {
        // TODO: this was copied from TransactionScopedSession, but does it need to be the same???
        if (isInTransaction()) {
            StatelessSession session = (StatelessSession) transactionSynchronizationRegistry.getResource(sessionKey);
            if (session != null) {
                return new SessionResult(session, false, true);
            }
            StatelessSession newSession = jtaSessionOpener.openSession();
            // The session has automatically joined the JTA transaction when it was constructed.
            transactionSynchronizationRegistry.putResource(sessionKey, newSession);
            return new SessionResult(newSession, false, true);
        } else if (requestScopedSessionEnabled) {
            if (Arc.container().requestContext().isActive()) {
                RequestScopedStatelessSessionHolder requestScopedSessions = this.requestScopedSessions.get();
                return new SessionResult(requestScopedSessions.getOrCreateSession(unitName, sessionFactory),
                        false, false);
            } else {
                throw new ContextNotActiveException(
                        "Cannot use the StatelessSession because neither a transaction nor a CDI request context is active."
                                + " Consider adding @Transactional to your method to automatically activate a transaction,"
                                + " or @ActivateRequestContext if you have valid reasons not to use transactions.");
            }
        } else {
            throw new ContextNotActiveException(
                    "Cannot use the StatelessSession because no transaction is active."
                            + " Consider adding @Transactional to your method to automatically activate a transaction,"
                            + " or set '" + HibernateOrmRuntimeConfig.extensionPropertyKey("request-scoped.enabled")
                            + "' to 'true' if you have valid reasons not to use transactions.");
        }
    }

    private void checkBlocking() {
        if (!BlockingOperationControl.isBlockingAllowed()) {
            throw new BlockingOperationNotAllowedException(
                    "You have attempted to perform a blocking operation on a IO thread. This is not allowed, as blocking the IO thread will cause major performance issues with your application. If you want to perform blocking StatelessSession operations make sure you are doing it from a worker thread.");
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Annotate the calling method with @Transactional (most common fix)
  2. Annotate with @ActivateRequestContext if you intentionally want a request-scoped session without a transaction (request-scoped.enabled=true)
  3. Start a programmatic transaction with QuarkusTransaction.requiring(...) around the StatelessSession calls
  4. Check that the calling thread actually carries CDI request context if you expected it to (e.g. don't pass the bean into raw worker threads)

Example fix

// before
@Scheduled(every = "10s")
void cleanup() {
    statelessSession.createQuery("delete from Token t where t.expiry < :now")...
}
// after
@Transactional
@Scheduled(every = "10s")
void cleanup() {
    statelessSession.createQuery("delete from Token t where t.expiry < :now")...
}
Defensive patterns

Strategy: validation

Validate before calling

import io.quarkus.arc.Arc;
import io.quarkus.narayana.jta.QuarkusTransaction;
boolean ok = QuarkusTransaction.isActive() || Arc.container().requestContext().isActive();
if (!ok) {
    throw new IllegalStateException("StatelessSession needs @Transactional or @ActivateRequestContext here");
}
statelessSession.refresh(entity);

Type guard

static boolean statelessSessionUsable() {
    return io.quarkus.narayana.jta.QuarkusTransaction.isActive()
        || (io.quarkus.arc.Arc.container() != null
            && io.quarkus.arc.Arc.container().requestContext().isActive());
}

Try / catch

try {
    statelessSession.refresh(entity);
} catch (jakarta.enterprise.context.ContextNotActiveException e) {
    io.quarkus.narayana.jta.QuarkusTransaction.requiring(() -> statelessSession.refresh(entity));
}

Prevention

When it happens

Trigger: Invoking any StatelessSession operation (refresh, createQuery, createNamedQuery, createNativeQuery, createNamedStoredProcedureQuery, createStoredProcedureQuery) from a thread where no JTA transaction is active AND the CDI request context is not active, while request-scoped sessions are enabled.

Common situations: @Scheduled tasks, Vert.x event-loop or messaging (Kafka) callbacks without @Transactional, manually spawned ExecutorService threads, startup/init code (StartupEvent observers) that touches the StatelessSession before any scope is active.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/b070c88382d2620a. Report an issue: GitHub.