{"record":{"id":"edba7de00d9afac0","repo":"hibernate/hibernate-orm","slug":"is-closed","errorCode":null,"errorMessage":"{} is closed","messagePattern":"(.+?) is closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java","lineNumber":39,"sourceCode":" * Base support for {@link LogicalConnection} implementations\n *\n * @author Steve Ebersole\n */\npublic abstract class AbstractLogicalConnectionImplementor implements LogicalConnectionImplementor, PhysicalJdbcTransaction {\n\n\t@Nonnull\n\tprivate TransactionStatus status = TransactionStatus.NOT_ACTIVE;\n\n\t@Override\n\t@Nonnull\n\tpublic PhysicalJdbcTransaction getPhysicalJdbcTransaction() {\n\t\terrorIfClosed();\n\t\treturn this;\n\t}\n\n\tprotected void errorIfClosed() {\n\t\tif ( !isOpen() ) {\n\t\t\tthrow new IllegalStateException( this + \" is closed\" );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void afterStatement() {\n\t}\n\n\t@Override\n\tpublic void beforeTransactionCompletion() {\n\t}\n\n\t@Override\n\tpublic void afterTransaction() {\n\t\tgetResourceRegistry().releaseResources();\n\t}\n\n\t// PhysicalJdbcTransaction impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java#L21-L57","documentation":"AbstractLogicalConnectionImplementor backs the logical JDBC connection of every Hibernate Session/EntityManager. Operations that need the physical transaction handle call errorIfClosed() first, which throws IllegalStateException('<LogicalConnectionImpl...> is closed') once the logical connection - i.e. the session - has been closed. Any use of a closed session's connection/transaction layer trips this guard.","triggerScenarios":"Calling getTransaction().begin()/commit(), obtaining the connection, or running any JDBC-level operation on a Session/EntityManager that was already closed; typically lazy loading, commit, or shared-helper access that runs after em.close().","commonSituations":"Lazy proxies or detached graphs accessed after the session closed; entity managers shared across threads where one thread closes while another still uses it; async processing holding a stale EM; missing try-with-resources so close happens earlier than expected.","solutions":["Guard with isOpen() before using a possibly-closed session, or restructure to try-with-resources so close is always the last operation.","Complete lazy loading before closing: use join fetch, EntityGraphs, or DTO projections instead of lazy proxies that outlive the session.","Keep EntityManager usage single-threaded and never reuse one after close().","Catch IllegalStateException around the affected block to convert it into a domain-meaningful error (e.g. 'operation on detached data')."],"exampleFix":"// before\nem.close();\n// ... later ...\n    em.getTransaction().commit(); // IllegalStateException: LogicalConnection... is closed\n\n// after\ntry (EntityManager em = emf.createEntityManager()) {\n    em.getTransaction().begin();\n    // work\n    em.getTransaction().commit();\n} // close always happens last","handlingStrategy":"validation","validationCode":"// guard shared helpers that may run after close\nstatic void requireOpen(EntityManager em) {\n    if (!em.isOpen()) {\n        throw new IllegalStateException(\"EntityManager is closed; open a new one for this operation\");\n    }\n}\n\nrequireOpen(em);\nem.getTransaction().commit();","typeGuard":null,"tryCatchPattern":"try {\n    em.getTransaction().commit();\n} catch (IllegalStateException e) {\n    // '<LogicalConnection...> is closed': session was closed before commit\n    // treat as a usage bug (closed/detached access), not a retryable failure\n    throw new SessionLifecycleException(\"Operation on closed session\", e);\n}","preventionTips":["Use try-with-resources for EntityManager/Session lifecycles so close is always last.","Fetch all lazy data before closing (join fetch, EntityGraph, DTO projection).","Never share an EntityManager across threads or reuse it after close().","Add isOpen() guards in shared helper/util code that receives sessions."],"tags":["hibernate","session","lifecycle","connection","entity-manager"],"backgroundTag":"session-already-closed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}