{"record":{"id":"6d00415292f63f10","repo":"hibernate/hibernate-orm","slug":"entitymanager-was-already-closed","errorCode":null,"errorMessage":"EntityManager was already closed","messagePattern":"EntityManager was already closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java","lineNumber":352,"sourceCode":"\t}\n\n\tprivate void internalClear() {\n\t\tpersistenceContext.clear();\n\t\tactionQueue.clear();\n\t\teventListenerGroups.eventListenerGroup_CLEAR\n\t\t\t\t.fireLazyEventOnEachListener( this::createClearEvent, ClearEventListener::onClear );\n\t}\n\n\tprivate ClearEvent createClearEvent() {\n\t\treturn new ClearEvent( this );\n\t}\n\n\t@Override\n\tpublic void close() {\n\t\tcheckSessionReentrancy();\n\t\tif ( isClosed() ) {\n\t\t\tif ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) {\n\t\t\t\tthrow new IllegalStateException( \"EntityManager was already closed\" );\n\t\t\t}\n\t\t\tSESSION_LOGGER.alreadyClosed();\n\t\t}\n\t\telse {\n\t\t\tfinal var preCloseException = getFactory().preClose( this );\n\t\t\ttry {\n\t\t\t\tcloseWithoutOpenChecks();\n\t\t\t}\n\t\t\tcatch (RuntimeException e) {\n\t\t\t\tif ( preCloseException != null ) {\n\t\t\t\t\te.addSuppressed( preCloseException );\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\tif ( preCloseException != null ) {\n\t\t\t\tthrow preCloseException;\n\t\t\t}\n\t\t}","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java#L334-L370","documentation":"SessionImpl.close() mirrors the factory: closing twice is normally just logged, but with JPA closed compliance enabled (hibernate.jpa.compliance.closed) the second close throws IllegalStateException('EntityManager was already closed'). The check runs after checkSessionReentrancy(), so closing from within the session's own callback also fails. JPA containers rely on this strictness.","triggerScenarios":"Calling close() twice on the same Session/EntityManager with compliance enabled — e.g. try-with-resources plus a manual close, or an application-layer decorator and the container both closing. Note close() also swallows nothing: if the first close threw mid-way, status may not be CLOSED and behavior differs.","commonSituations":"Wrapper/decorator EntityManager beans whose close() delegates and also closes the delegate; finally blocks plus try-with-resources around the same EM; servlet filters closing injected container-managed EMs (which the container also closes); enabling compliance in Quarkus/Spring and surfacing latent double closes.","solutions":["Guard every close: if (em != null && em.isOpen()) em.close();","Use exactly one close strategy per EM — try-with-resources OR container management, never both","In decorators, forward isOpen() and only close what you own","Never explicitly close container-managed (injected @PersistenceContext) EntityManagers"],"exampleFix":"// before\ntry (EntityManager em = emf.createEntityManager()) {\n    // ...\n} // container/proxy also closes -> IllegalStateException under compliance\n\n// after\nEntityManager em = emf.createEntityManager();\ntry {\n    // ...\n} finally {\n    if (em.isOpen()) {\n        em.close(); // single, guarded close\n    }\n}","handlingStrategy":"validation","validationCode":"public static void closeQuietly(EntityManager em) {\n    if (em != null && em.isOpen()) {\n        em.close();\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    em.close();\n} catch (IllegalStateException e) {\n    // already closed under JPA compliance — idempotent close, safe to ignore\n    LOG.debug(\"EntityManager already closed\", e);\n}","preventionTips":["Use exactly one closing mechanism per EntityManager (try-with-resources OR container-managed)","Never close injected @PersistenceContext EntityManagers yourself","In decorators, delegate close() once and make isOpen() accurate"],"tags":["hibernate","jpa","session","double-close","compliance","lifecycle"],"backgroundTag":"double-close","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}