{"record":{"id":"974ebf8d3a5b3deb","repo":"hibernate/hibernate-orm","slug":"cannot-lazily-initialize-collection","errorCode":null,"errorMessage":"Cannot lazily initialize collection","messagePattern":"Cannot lazily initialize collection","errorType":"exception","errorClass":"LazyInitializationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java","lineNumber":667,"sourceCode":"\tprivate void throwLazyInitializationExceptionIfNotConnected() {\n\t\tif ( !isConnectedToSession() ) {\n\t\t\tthrowLazyInitializationException( \"no session or session was closed\" );\n\t\t}\n\t\tif ( !session.isConnected() ) {\n\t\t\tthrowLazyInitializationException( \"session is disconnected\" );\n\t\t}\n\t}\n\n\tprivate void throwLazyInitializationException(String message) {\n\t\tfinal var error = new StringBuilder( \"Cannot lazily initialize collection\" );\n\t\tif ( role != null ) {\n\t\t\terror.append( \" of role '\" ).append( role ).append( \"'\" );\n\t\t}\n\t\tif ( key != null ) {\n\t\t\terror.append( \" with key '\" ).append( key ).append( \"'\" );\n\t\t}\n\t\terror.append( \" (\" ).append( message ).append( \")\" );\n\t\tthrow new LazyInitializationException( error.toString() );\n\t}\n\n\tpublic static void checkPersister(PersistentCollection<?> collection, CollectionPersister persister) {\n\t\tif ( !collection.wasInitialized() && persister == null ) {\n\t\t\tthrow new LazyInitializationException( \"Cannot lazily initialize collection\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t+ \" (collection is being removed)\" );\n\t\t}\n\t}\n\n\tprotected final void setInitialized() {\n\t\tthis.initializing = false;\n\t\tthis.initialized = true;\n\t}\n\n\t@Override\n\tpublic boolean isInitializing() {\n\t\treturn initializing;\n\t}","sourceCodeStart":649,"sourceCodeEnd":685,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/collection/spi/AbstractPersistentCollection.java#L649-L685","documentation":"A lazy persistent collection stores its role and key; on first access it asks its owning session to load the data. throwLazyInitializationException fires when initialization is impossible because the session is closed or the collection is detached, producing the classic 'Cannot lazily initialize collection of role X with key Y' error. The message names the exact association that was touched outside a live session.","triggerScenarios":"Calling size(), iterator(), stream(), contains() or get() on a lazy @OneToMany collection after the owning session/EntityManager closed; serializing detached entities to JSON; touching the collection in another thread or after transaction end with OSIV disabled.","commonSituations":"Spring MVC controllers returning JPA entities with lazy relations after the service transaction ended; async jobs or executors receiving detached entities; unit tests reading collections outside transactional scope.","solutions":["Initialize the collection inside the session: Hibernate.initialize(parent.getChildren()) or a touch like size() within the transaction","Fetch what you need in the query: JOIN FETCH, @EntityGraph, or @Fetch(JOIN) for that read path","Project to DTOs inside the service layer instead of returning entities","Widen the @Transactional boundary so the whole read happens in one open session"],"exampleFix":"// before\n@Transactional(readOnly = true)\npublic Order getOrder(Long id) { return repo.findById(id).orElseThrow(); }\n// caller after commit: order.getLines().size(); -> LazyInitializationException\n\n// after\n@Transactional(readOnly = true)\npublic Order getOrder(Long id) {\n    return em.createQuery(\n            \"select o from Order o join fetch o.lines where o.id = :id\", Order.class)\n            .setParameter(\"id\", id).getSingleResult();\n}","handlingStrategy":"validation","validationCode":"if (order.getLines() instanceof PersistentCollection pc\n        && !pc.wasInitialized()\n        && !session.isOpen()) {\n    throw new IllegalStateException(\n            \"order.lines is lazy and the session is closed - initialize inside the transaction\");\n}","typeGuard":"static boolean isSafeToAccess(Collection<?> c, SharedSessionContract session) {\n    return !(c instanceof PersistentCollection pc)\n            || pc.wasInitialized()\n            || (session != null && session.isOpen());\n}","tryCatchPattern":"try {\n    return order.getLines().size();\n} catch (LazyInitializationException e) {\n    // recover by reloading the owner in a fresh session\n    try (Session s = sessionFactory.openSession()) {\n        return s.find(Order.class, order.getId()).getLines().size();\n    }\n}","preventionTips":["Initialize lazy associations inside the owning transaction (Hibernate.initialize or a touch)","Use join fetch / @EntityGraph for read paths that need the data","Return DTO projections from API layers instead of managed entities","Make OSIV (open-in-view) decisions explicit and documented per project"],"tags":["hibernate","lazy-loading","session","fetching","detached"],"backgroundTag":"lazyinitializationexception","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}