hibernate/hibernate-orm · error · AnnotationException

Attribute '{}' is annotated '@Bag' and may not also be annot

Error message

Attribute '{}' is annotated '@Bag' and may not also be annotated '@ListIndexBase'

What it means

@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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java:936

			MemberDetails property,
			MetadataBuildingContext buildingContext) {
		if ( property.isArray() ) {
			return CollectionClassification.ARRAY;
		}

		final var modelsContext = buildingContext.getBootstrapContext().getModelsContext();
		if ( !property.hasAnnotationUsage( Bag.class, modelsContext ) ) {
			return determineCollectionClassification( determineSemanticJavaType( property ), property, buildingContext );
		}

		if ( property.hasAnnotationUsage( OrderColumn.class, modelsContext ) ) {
			throw new AnnotationException( "Attribute '"
					+ qualify( property.getDeclaringType().getName(), property.getName() )
					+ "' is annotated '@Bag' and may not also be annotated '@OrderColumn'" );
		}

		if ( property.hasAnnotationUsage( ListIndexBase.class, modelsContext ) ) {
			throw new AnnotationException( "Attribute '"
					+ qualify( property.getDeclaringType().getName(), property.getName() )
					+ "' is annotated '@Bag' and may not also be annotated '@ListIndexBase'" );
		}

		final var collectionJavaType = property.getType().determineRawClass().toJavaClass();
		if ( java.util.List.class.equals( collectionJavaType )
				|| java.util.Collection.class.equals( collectionJavaType ) ) {
			return CollectionClassification.BAG;
		}
		else {
			throw new AnnotationException(
					String.format(
							Locale.ROOT,
							"Attribute '%s.%s' of type '%s' is annotated '@Bag' (bags are of type '%s' or '%s')",
							property.getDeclaringType().getName(),
							property.getName(),
							collectionJavaType.getName(),
							java.util.List.class.getName(),

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove @ListIndexBase if bag semantics is what you want (no index at all)
  2. Or remove @Bag and keep @ListIndexBase together with @OrderColumn for a 1-based indexed list
  3. Audit for other index-related leftovers (@OrderColumn is checked separately with the same conflict)

Example fix

// before
@Bag
@ListIndexBase(1)
List<Item> items;   // error: index base makes no sense on a bag

// after
@OrderColumn
@ListIndexBase(1)
List<Item> items;   // index base applies to the order column
// or remove @ListIndexBase and keep @Bag
Defensive patterns

Strategy: validation

Validate before calling

// Reject @Bag combined with @OrderColumn or @ListIndexBase
static void checkBagConflicts(Class<?>... entities) {
    for ( Class<?> c : entities ) {
        for ( Field f : c.getDeclaredFields() ) {
            if ( f.isAnnotationPresent( Bag.class )
                    && ( f.isAnnotationPresent( OrderColumn.class )
                         || f.isAnnotationPresent( ListIndexBase.class ) ) ) {
                throw new IllegalStateException( "@Bag conflicts with an order/index annotation on "
                    + c.getName() + "." + f.getName() );
            }
        }
    }
}

Prevention

When it happens

Trigger: A property has @Bag and also hasAnnotationUsage(ListIndexBase.class) during determineCollectionClassification; the check runs whenever @Bag is present.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/c320b5c45aad14ed. Report an issue: GitHub.