{"record":{"id":"61ebc4f251e031c2","repo":"hibernate/hibernate-orm","slug":"bags-don-t-have-indexes","errorCode":null,"errorMessage":"Bags don't have indexes : ","messagePattern":"Bags don't have indexes : ","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java","lineNumber":532,"sourceCode":"\t}\n\n\t@Override\n\tpublic void clear() {\n\t\tif ( isClearQueueEnabled() ) {\n\t\t\tqueueOperation( new Clear() );\n\t\t}\n\t\telse {\n\t\t\tinitialize( true );\n\t\t\tif ( !collection.isEmpty() ) {\n\t\t\t\tcollection.clear();\n\t\t\t\tdirty();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object getIndex(Object entry, int i, CollectionPersister persister) {\n\t\tthrow new UnsupportedOperationException( \"Bags don't have indexes : \" + persister.getRole() );\n\t}\n\n\t@Override\n\tpublic Object getElement(Object entry) {\n\t\treturn entry;\n\t}\n\n\t@Override\n\tpublic Object getSnapshotElement(Object entry, int i) {\n\t\tfinal List<?> sn = (List<?>) getSnapshot();\n\t\treturn sn.get( i );\n\t}\n\n\t/**\n\t * Count how many times the given object occurs in the elements\n\t *\n\t * @param o The object to check\n\t *","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java#L514-L550","documentation":"getIndex is part of the collection SPI used for indexed collections (lists with an order column, maps). A bag has no positional index by definition, so PersistentBag implements getIndex by throwing UnsupportedOperationException with the collection role. The throw means some code path asked this bag's entries for element indexes: usually mapping metadata that implies an index while the runtime collection is a bag, or direct use of the collection SPI.","triggerScenarios":"Mapping declared as indexed (<list>, @OrderColumn/@ListIndexBase) while the runtime wrapper or persister resolves the collection as a bag; programmatic calls to PersistentCollection#getIndex; stale or duplicate mappings after partial refactors.","commonSituations":"Switching a mapping between <bag> and <list> inconsistently; custom framework code driving the collection SPI directly; stale compiled mappings shadowing updated ones.","solutions":["Make the mapping consistent: <list> or @OrderColumn with a List field for indexed collections, plain bag/Collection for unordered","Ensure the Java field type matches the mapping kind (List for indexed mappings)","Clean rebuild and purge stale hbm.xml resources or duplicate mapping files","Do not call PersistentCollection#getIndex yourself; use the collection's public API"],"exampleFix":"// before\n@OneToMany(mappedBy = \"order\")\nprivate Collection<OrderLine> lines; // index-dependent code path against a bag\n\n// after\n@OneToMany(mappedBy = \"order\")\n@OrderColumn(name = \"line_no\")\nprivate List<OrderLine> lines;","handlingStrategy":"validation","validationCode":"CollectionPersister cp = sessionFactory.getDomainModel()\n        .findCollectionDescriptor(Order.class.getName() + \".lines\");\nif (cp == null || !cp.hasIndex()) {\n    // not an indexed collection; skip index-dependent logic\n}","typeGuard":"static boolean hasIndexColumn(Field field) {\n    return field.isAnnotationPresent(OrderColumn.class)\n            || Map.class.isAssignableFrom(field.getType());\n}","tryCatchPattern":null,"preventionTips":["Decide ordering at mapping time: bags are unordered, lists are indexed","Keep field type and mapping kind in sync","Do not rely on positional access for bag-mapped collections"],"tags":["hibernate","collection-mapping","bag","index","unsupported-operation"],"backgroundTag":"indexed-access-on-bag","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}