{"record":{"id":"ec03a8b49bded13c","repo":"quarkusio/quarkus","slug":"not-supported-for-transaction-scoped-entity-manage","errorCode":null,"errorMessage":"Not supported for transaction scoped entity managers","messagePattern":"Not supported for transaction scoped entity managers","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java","lineNumber":617,"sourceCode":"        if (cls.isAssignableFrom(Session.class)) {\n            return (T) this;\n        }\n        checkBlocking();\n        try (SessionResult emr = acquireSession()) {\n            return emr.session.unwrap(cls);\n        }\n    }\n\n    @Override\n    public Object getDelegate() {\n        try (SessionResult emr = acquireSession()) {\n            return emr.session.getDelegate();\n        }\n    }\n\n    @Override\n    public void close() {\n        throw new IllegalStateException(\"Not supported for transaction scoped entity managers\");\n    }\n\n    @Override\n    public boolean isOpen() {\n        return true;\n    }\n\n    @Override\n    public Transaction getTransaction() {\n        throw new IllegalStateException(\"Not supported for JTA entity managers\");\n    }\n\n    @Override\n    public EntityManagerFactory getEntityManagerFactory() {\n        return sessionFactory;\n    }\n\n    @Override","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java#L599-L635","documentation":"TransactionScopedSession.close() always throws IllegalStateException because the lifecycle of a transaction-scoped EntityManager is owned by Quarkus/ArC: a new session is acquired per transaction and closed automatically when the transaction ends. Application code must never close it manually, so close() is intentionally unsupported.","triggerScenarios":"Calling em.close() (or session.close()) on an injected, transaction-scoped EntityManager, typically copied from Java SE/Java EE code that managed its own EntityManagerFactory.","commonSituations":"Porting a DAO from a plain JPA app with emf.createEntityManager()/em.close(); cleanup code in @PreDestroy or finally blocks closing the injected EM; over-aggressive resource cleanup added during a refactor.","solutions":["Delete the em.close() call — Quarkus closes the session automatically when the transaction or request scope ends","Use @Inject EntityManager and let CDI handle lifecycle; keep methods @Transactional for writes","If you truly need manual lifecycle, switch to an application-scoped (extended) EntityManager via a producer using PersistenceUnit extension semantics, but avoid closing injected EMs","Unwrap only for operations: em.unwrap(Session.class) — do not close the result"],"exampleFix":"// before\n@Transactional\npublic void save(MyEntity e) {\n    em.persist(e);\n    em.close(); // throws IllegalStateException\n}\n// after\n@Transactional\npublic void save(MyEntity e) {\n    em.persist(e); // Quarkus closes the session itself\n}","handlingStrategy":"type-guard","validationCode":"// never close an injected, transaction-scoped EntityManager\nif (em.isJoinedToTransaction() || em.isOpen()) {\n    // safe to use, NOT safe to close\n    em.persist(entity); // do NOT call em.close()\n}","typeGuard":"boolean isContainerManaged(EntityManager em) {\n    // container-managed Quarkus EMs are @TransactionScoped and close() is unsupported\n    return em != null && em.isOpen()\n        && CDI.current().select(EntityManager.class).stream().anyMatch(em::equals);\n}\n// guard: only close EMs you created yourself from an EntityManagerFactory","tryCatchPattern":"try {\n    em.close();\n} catch (IllegalStateException e) {\n    // container-managed EM: remove the close call; Quarkus manages lifecycle\n    log.debug(\"Skipping close of transaction-scoped EntityManager\", e);\n}","preventionTips":["Never copy SE/Java EE EM lifecycle code (emf.createEntityManager/close) into Quarkus services","Rely on CDI and transaction scope to manage EntityManager lifecycle","If manual EMs are needed, create them from PersistenceUnit and close them in try-with-resources — never the injected one","Code-review for em.close() and session.close() on injected EMs"],"tags":["jpa","hibernate-orm","lifecycle","quarkus"],"backgroundTag":"entity-manager-lifecycle","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}