quarkusio/quarkus · error · ContextNotActiveException

Cannot use the EntityManager/Session because no transaction

Error message

Cannot use the EntityManager/Session because no transaction is active. Consider adding @Transactional to your method to automatically activate a transaction, or set 'quarkus.hibernate-orm.request-scoped.enabled' to 'true' if you have valid reasons not to use transactions.

What it means

This is the default-path failure of acquireSession in TransactionScopedSession: when request-scoped sessions are disabled (the default, quarkus.hibernate-orm.request-scoped.enabled=false), a session may ONLY be obtained inside an active transaction. Any EntityManager operation issued outside @Transactional therefore throws ContextNotActiveException, pointing the developer at @Transactional or at enabling request-scoped sessions.

Source

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

            // See:
            // - io.quarkus.hibernate.orm.runtime.boot.FastBootMetadataBuilder.mergeSettings
            // - org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.joinJtaTransaction
            // - org.hibernate.internal.SessionImpl.beforeTransactionCompletion
            // - org.hibernate.internal.SessionImpl.afterTransactionCompletion
            return new SessionResult(newSession, false, true);
        } else if (requestScopedSessionEnabled) {
            if (Arc.container().requestContext().isActive()) {
                RequestScopedSessionHolder requestScopedSessions = this.requestScopedSessions.get();
                return new SessionResult(requestScopedSessions.getOrCreateSession(unitName, sessionFactory),
                        false, false);
            } else {
                throw new ContextNotActiveException(
                        "Cannot use the EntityManager/Session 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 EntityManager/Session 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 EntityManager operations make sure you are doing it from a worker thread.");
        }
    }

    private boolean isInTransaction() {
        try {
            switch (transactionManager.getStatus()) {
                case Status.STATUS_ACTIVE:

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add @Transactional to the method performing the EntityManager call (writes require it; reads also get a session this way).
  2. If you need read-only EM usage without transactions, set quarkus.hibernate-orm.request-scoped.enabled=true so a request-context session is used instead.
  3. Ensure the call runs inside a CDI-managed bean (REST resource, @ApplicationScoped service) so the ArC interceptor for @Transactional fires — direct calls on `new MyService()` bypass interception.
  4. For programmatic control, use the injected Session/EntityManager within a UserTransaction or annotate a smaller inner method to scope the transaction.

Example fix

// before
@ApplicationScoped
public class UserRepository {
    @Inject EntityManager em;
    public void save(User u) {
        em.persist(u); // ContextNotActiveException
    }
}

// after
@ApplicationScoped
public class UserRepository {
    @Inject EntityManager em;
    @Transactional
    public void save(User u) {
        em.persist(u);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

boolean emUsableWithoutRequestScope() {
    // request-scoped disabled (default): EM only works inside a transaction
    return quarkusTransactionActive();
}
// e.g. check via the injected EntityManager is not possible; check transaction status:
boolean inTx() {
    return !TransactionManager.instance().getStatus()
        .map(s -> s == Status.STATUS_NO_TRANSACTION).orElse(true);
}

Try / catch

try {
    em.find(User.class, id);
} catch (ContextNotActiveException e) {
    // no transaction: retry through a @Transactional service
    return userRepository.find(id);
}

Prevention

When it happens

Trigger: Injecting EntityManager (backed by TransactionScopedSession) and calling persist/merge/remove/find/findMultiple/getReference from code with no active transaction and request-scoped sessions disabled — e.g. a REST resource method without @Transactional, a scheduled job, a startup observer, or a Vert.x route handler calling the EM directly.

Common situations: Forgetting @Transactional on a service method that writes; calling the EM from a QuarkusTest before the request/transaction scope starts; migrating code that used @Inject EntityManager expecting an application-scoped session; enabling/disabling request-scoped.enabled across versions and changing behavior.

Related errors


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