hibernate/hibernate-orm · error · UnsupportedOperationException

Bags don't have indexes :

Error message

Bags don't have indexes : 

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentBag.java:532

	}

	@Override
	public void clear() {
		if ( isClearQueueEnabled() ) {
			queueOperation( new Clear() );
		}
		else {
			initialize( true );
			if ( !collection.isEmpty() ) {
				collection.clear();
				dirty();
			}
		}
	}

	@Override
	public Object getIndex(Object entry, int i, CollectionPersister persister) {
		throw new UnsupportedOperationException( "Bags don't have indexes : " + persister.getRole() );
	}

	@Override
	public Object getElement(Object entry) {
		return entry;
	}

	@Override
	public Object getSnapshotElement(Object entry, int i) {
		final List<?> sn = (List<?>) getSnapshot();
		return sn.get( i );
	}

	/**
	 * Count how many times the given object occurs in the elements
	 *
	 * @param o The object to check
	 *

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the mapping consistent: <list> or @OrderColumn with a List field for indexed collections, plain bag/Collection for unordered
  2. Ensure the Java field type matches the mapping kind (List for indexed mappings)
  3. Clean rebuild and purge stale hbm.xml resources or duplicate mapping files
  4. Do not call PersistentCollection#getIndex yourself; use the collection's public API

Example fix

// before
@OneToMany(mappedBy = "order")
private Collection<OrderLine> lines; // index-dependent code path against a bag

// after
@OneToMany(mappedBy = "order")
@OrderColumn(name = "line_no")
private List<OrderLine> lines;
Defensive patterns

Strategy: validation

Validate before calling

CollectionPersister cp = sessionFactory.getDomainModel()
        .findCollectionDescriptor(Order.class.getName() + ".lines");
if (cp == null || !cp.hasIndex()) {
    // not an indexed collection; skip index-dependent logic
}

Type guard

static boolean hasIndexColumn(Field field) {
    return field.isAnnotationPresent(OrderColumn.class)
            || Map.class.isAssignableFrom(field.getType());
}

Prevention

When it happens

Trigger: 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.

Common situations: Switching a mapping between <bag> and <list> inconsistently; custom framework code driving the collection SPI directly; stale compiled mappings shadowing updated ones.

Related errors


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