quarkusio/quarkus · error · UnsupportedOperationException

This build of Hibernate ORM doesn't support 'thread' value f

Error message

This build of Hibernate ORM doesn't support 'thread' value for configuration property hibernate.current_session_context_class

What it means

In native (GraalVM) images, Quarkus substitutes Hibernate ORM's ThreadLocalSessionContext with a stub whose constructor always throws UnsupportedOperationException. The 'thread' JTA-less session-context strategy relies on reflection/thread-local machinery that Quarkus does not support, so it is deliberately disabled at build time. If you got this, your persistence unit is configured with hibernate.current_session_context_class=thread and bootstrapped in a native executable.

Source

Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/graal/context/Substitute_ThreadLocalSessionContext.java:16

package io.quarkus.hibernate.orm.runtime.graal.context;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;

import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;

@TargetClass(className = "org.hibernate.context.internal.ThreadLocalSessionContext")
public final class Substitute_ThreadLocalSessionContext {

    @Substitute
    public Substitute_ThreadLocalSessionContext(SessionFactoryImplementor factory) {
        throw new UnsupportedOperationException(
                "This build of Hibernate ORM doesn't support 'thread' value for configuration property"
                        + AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS);
    }

    @Substitute
    public Session currentSession() throws HibernateException {
        return null;
    }

}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the hibernate.current_session_context_class=thread setting entirely; Quarkus manages session/context binding itself.
  2. Instead of session.unwrap/getCurrentSession with 'thread', inject an EntityManager (or Session) via CDI, e.g. @Inject EntityManager em, ideally inside a @Transactional method.
  3. If you must keep legacy code, run in JVM mode (not native) where the substitution does not apply — but prefer refactoring.

Example fix

// before (persistence.xml or properties)
hibernate.current_session_context_class=thread
Session s = sessionFactory.getCurrentSession();

// after (Quarkus)
@Inject EntityManager em;
@Transactional
public void doWork() { em.persist(new Entity()); }
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast if a native build would break
if (config.containsProperty("quarkus.hibernate-orm.relationships")) { /* check pu config */ }
// simplest: assert the setting is absent
assert !puProperties.containsKey(AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS)
    : "Remove hibernate.current_session_context_class=thread; Quarkus manages session context";

Prevention

When it happens

Trigger: Setting hibernate.current_session_context_class=thread (via quarkus.hibernate-orm.* config or persistence.xml AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS) so Hibernate instantiates ThreadLocalSessionContext, whose @Substitute constructor throws during SessionFactory build in a native build.

Common situations: Porting a classic Java EE / Spring-style application to Quarkus native that relied on 'thread' session contexts and getCurrentSession(); copying persistence.xml settings from a non-Quarkus project; misunderstanding that Quarkus manages sessions via its own integration (e.g. transaction-scoped sessions through ArC/transaction APIs).

Related errors


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