{"record":{"id":"60fd0564c7b42600","repo":"hibernate/hibernate-orm","slug":"queued-clear-cannot-be-used-with-orphan-delete-60fd05","errorCode":null,"errorMessage":"queued clear cannot be used with orphan delete","messagePattern":"queued clear cannot be used with orphan delete","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java","lineNumber":664,"sourceCode":"\t@Override\n\tpublic boolean entryExists(Object entry, int i) {\n\t\treturn entry!=null;\n\t}\n\n\tfinal class Clear implements DelayedOperation<E> {\n\t\t@Override\n\t\tpublic void operate() {\n\t\t\tlist.clear();\n\t\t}\n\n\t\t@Override\n\t\tpublic E getAddedInstance() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic E getOrphan() {\n\t\t\tthrow new UnsupportedOperationException( \"queued clear cannot be used with orphan delete\" );\n\t\t}\n\t}\n\n\tprotected final class SimpleAdd extends AbstractValueDelayedOperation {\n\n\t\tpublic SimpleAdd(E addedValue) {\n\t\t\tsuper( addedValue, null );\n\t\t}\n\n\t\t@Override\n\t\tpublic void operate() {\n\t\t\tlist.add( getAddedInstance() );\n\t\t}\n\t}\n\n\tabstract class AbstractListValueDelayedOperation extends AbstractValueDelayedOperation {\n\t\tprivate final int index;\n","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentList.java#L646-L682","documentation":"PersistentList queues operations on an uninitialized lazy collection, so clear() on an uninitialized list becomes a queued Clear operation instead of running immediately. Because a bulk Clear cannot know which individual elements were removed, its getOrphan() throws UnsupportedOperationException when Hibernate needs per-element orphan information — which happens when the association has orphan delete enabled (orphanRemoval=true / delete-orphan) at flush time.","triggerScenarios":"@OneToMany(cascade = ALL, orphanRemoval = true) List<Item> children; the parent is loaded without touching children; code calls parent.getChildren().clear() (typical 'replace all children' pattern); at flush the collection role requires orphan deletion and calls getOrphan() on the queued Clear.","commonSituations":"Replace-children flows (clear() + addAll()) on lazy collections; entity copy/merge utilities that clear target collections; switching a mapping from EAGER to LAZY making the collection uninitialized where clear() used to run directly; upgrading Hibernate versions where queueing behavior changed.","solutions":["Force initialization before clearing: call Hibernate.initialize(parent.getChildren()) or touch size() first, so clear() executes directly and orphans are computed from the snapshot","Remove elements individually on the initialized collection (iterator.remove()/removeIf) so each removal carries its own orphan","Reconsider orphanRemoval=true for associations whose normal use is full clear-and-replace","Add an integration test that runs the clear+flush flow against the real mapping"],"exampleFix":"// before\nparent.getChildren().clear();   // uninitialized -> queued Clear\nparent.getChildren().addAll(newKids);\ntx.commit();                    // flush -> UnsupportedOperationException\n\n// after\nHibernate.initialize(parent.getChildren()); // force init\nparent.getChildren().clear();               // direct clear, orphans tracked\nparent.getChildren().addAll(newKids);","handlingStrategy":"validation","validationCode":"List<Item> children = parent.getChildren();\nif (children instanceof org.hibernate.collection.spi.PersistentCollection pc && !pc.wasInitialized()) {\n    org.hibernate.Hibernate.initialize(children); // force init so clear() is not queued\n}\nchildren.clear();","typeGuard":null,"tryCatchPattern":"try {\n    tx.commit();\n} catch (org.hibernate.HibernateException e) {\n    if (e instanceof java.util.UnsupportedOperationException\n            || e.getCause() instanceof java.util.UnsupportedOperationException uoe\n            && String.valueOf(uoe.getMessage()).contains(\"queued clear\")) {\n        throw new IllegalStateException(\"clear() on an uninitialized collection with orphanRemoval is not supported; initialize the collection first\", e);\n    }\n    throw e;\n}","preventionTips":["Initialize lazy collections before clear() whenever orphanRemoval=true","Prefer removeIf/iterator removal so each element carries its orphan","Add a flush-performing test for every clear-and-replace flow","Reserve orphanRemoval for associations with per-element semantics"],"tags":["hibernate","collections","orphan-removal","lazy-initialization","persistent-list","flush"],"backgroundTag":"orphan-removal-queued-clear","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}