{"record":{"id":"c320b5c45aad14ed","repo":"hibernate/hibernate-orm","slug":"attribute-is-annotated-bag-and-may-not-als-c320b5","errorCode":null,"errorMessage":"Attribute '{}' is annotated '@Bag' and may not also be annotated '@ListIndexBase'","messagePattern":"Attribute '(.+?)' is annotated '@Bag' and may not also be annotated '@ListIndexBase'","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java","lineNumber":936,"sourceCode":"\t\t\tMemberDetails property,\n\t\t\tMetadataBuildingContext buildingContext) {\n\t\tif ( property.isArray() ) {\n\t\t\treturn CollectionClassification.ARRAY;\n\t\t}\n\n\t\tfinal var modelsContext = buildingContext.getBootstrapContext().getModelsContext();\n\t\tif ( !property.hasAnnotationUsage( Bag.class, modelsContext ) ) {\n\t\t\treturn determineCollectionClassification( determineSemanticJavaType( property ), property, buildingContext );\n\t\t}\n\n\t\tif ( property.hasAnnotationUsage( OrderColumn.class, modelsContext ) ) {\n\t\t\tthrow new AnnotationException( \"Attribute '\"\n\t\t\t\t\t+ qualify( property.getDeclaringType().getName(), property.getName() )\n\t\t\t\t\t+ \"' is annotated '@Bag' and may not also be annotated '@OrderColumn'\" );\n\t\t}\n\n\t\tif ( property.hasAnnotationUsage( ListIndexBase.class, modelsContext ) ) {\n\t\t\tthrow new AnnotationException( \"Attribute '\"\n\t\t\t\t\t+ qualify( property.getDeclaringType().getName(), property.getName() )\n\t\t\t\t\t+ \"' is annotated '@Bag' and may not also be annotated '@ListIndexBase'\" );\n\t\t}\n\n\t\tfinal var collectionJavaType = property.getType().determineRawClass().toJavaClass();\n\t\tif ( java.util.List.class.equals( collectionJavaType )\n\t\t\t\t|| java.util.Collection.class.equals( collectionJavaType ) ) {\n\t\t\treturn CollectionClassification.BAG;\n\t\t}\n\t\telse {\n\t\t\tthrow new AnnotationException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\"Attribute '%s.%s' of type '%s' is annotated '@Bag' (bags are of type '%s' or '%s')\",\n\t\t\t\t\t\t\tproperty.getDeclaringType().getName(),\n\t\t\t\t\t\t\tproperty.getName(),\n\t\t\t\t\t\t\tcollectionJavaType.getName(),\n\t\t\t\t\t\t\tjava.util.List.class.getName(),","sourceCodeStart":918,"sourceCodeEnd":954,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java#L918-L954","documentation":"@ListIndexBase configures the base value of an order/list index, which only exists for indexed (LIST) collections. @Bag explicitly requests an unindexed, unordered BAG, so @ListIndexBase has nothing to attach to and CollectionBinder rejects the combination.","triggerScenarios":"A property has @Bag and also hasAnnotationUsage(ListIndexBase.class) during determineCollectionClassification; the check runs whenever @Bag is present.","commonSituations":"Migrating legacy @LazyCollection or @OrderBy mappings to @Bag while leaving @ListIndexBase in place; adding @ListIndexBase to fix 0- vs 1-based index issues on a mapping that was later switched to bag semantics.","solutions":["Remove @ListIndexBase if bag semantics is what you want (no index at all)","Or remove @Bag and keep @ListIndexBase together with @OrderColumn for a 1-based indexed list","Audit for other index-related leftovers (@OrderColumn is checked separately with the same conflict)"],"exampleFix":"// before\n@Bag\n@ListIndexBase(1)\nList<Item> items;   // error: index base makes no sense on a bag\n\n// after\n@OrderColumn\n@ListIndexBase(1)\nList<Item> items;   // index base applies to the order column\n// or remove @ListIndexBase and keep @Bag","handlingStrategy":"validation","validationCode":"// Reject @Bag combined with @OrderColumn or @ListIndexBase\nstatic void checkBagConflicts(Class<?>... entities) {\n    for ( Class<?> c : entities ) {\n        for ( Field f : c.getDeclaredFields() ) {\n            if ( f.isAnnotationPresent( Bag.class )\n                    && ( f.isAnnotationPresent( OrderColumn.class )\n                         || f.isAnnotationPresent( ListIndexBase.class ) ) ) {\n                throw new IllegalStateException( \"@Bag conflicts with an order/index annotation on \"\n                    + c.getName() + \".\" + f.getName() );\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember @ListIndexBase only pairs with @OrderColumn on indexed lists","After switching an attribute to @Bag, delete every index-related annotation from it","Cover collection mappings with a bootstrap test in CI"],"tags":["hibernate","bag","list-index-base","collection-semantics","annotation-binding"],"backgroundTag":"bag-annotation-conflict","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}