hibernate/hibernate-orm · error · IllegalStateException

Bag is not a list:

Error message

Bag is not a list: 

What it means

PersistentIdentifierBag (id-bag mapping) wraps any java.util.Collection; list-position operations go through bagAsList(), which only works when the wrapped collection is a List. If the id-bag was constructed around a non-List collection, list-style operations throw IllegalStateException with the collection's class name. As with PersistentBag, the runtime collection type does not support the list operations being attempted.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentIdentifierBag.java:99

	 * @param session The session
	 * @param coll The base elements
	 */
	public PersistentIdentifierBag(SharedSessionContractImplementor session, Collection<E> coll) {
		super( session );
		setCollection( coll );
		setInitialized();
		setDirectlyAccessible( true );
		identifiers = new HashMap<>();
	}

	private void setCollection(Collection<E> bag) {
		this.collection = bag;
		this.values = bag instanceof List<E> list ? list : null;
	}

	protected List<E> bagAsList() {
		if ( values == null ) {
			throw new IllegalStateException( "Bag is not a list: " + collection.getClass().getName() );
		}
		return values;
	}

	@Override
	public void initializeFromCache(CollectionPersister persister, Object disassembled, Object owner)
			throws HibernateException {
		final Serializable[] array = (Serializable[]) disassembled;
		final int size = array.length;

		assert identifiers == null;
		assert collection == null;

		identifiers = new HashMap<>();
		//noinspection unchecked
		setCollection( (Collection<E>) persister.getCollectionSemantics().instantiateRaw( size, persister ) );

		for ( int i = 0; i < size; i+=2 ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Declare the field as List and initialize with ArrayList for id-bag mappings
  2. Map set-like fields as Set instead of id-bag if set semantics are intended
  3. Avoid positional operations on identifier bags
  4. Add a convention check/test that bag and id-bag fields are initialized with ArrayList

Example fix

// before
@org.hibernate.annotations.CollectionId /* id-bag style mapping */
private Collection<Tag> tags = new HashSet<>(); // non-List backing -> bagAsList() throws

// after
@org.hibernate.annotations.CollectionId /* id-bag style mapping */
private List<Tag> tags = new ArrayList<>();
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(order.getTags() instanceof List)) {
    throw new IllegalStateException(
            "tags is id-bag mapped around a non-List collection; use ArrayList");
}

Type guard

static boolean supportsIndexAccess(Collection<?> collection) {
    return collection instanceof List;
}

Prevention

When it happens

Trigger: An id-bag mapped field (collection with <id-bag> or identifier-bag semantics) whose application-initialized value is a non-List Collection such as a HashSet; then indexed add/get or list-snapshot paths run against it.

Common situations: Fields initialized with HashSet or custom Collection implementations under id-bag mappings; refactors that changed the field initializer but kept the mapping; copy-pasted initializers across entity classes.

Related errors


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