hibernate/hibernate-orm · error · UnsupportedOperationException
generic collections don't have indexes
Error message
generic collections don't have indexes
What it means
CollectionType.indexOf (CollectionType.java:69) is the base implementation for collection types that have no positional index; it throws UnsupportedOperationException ('generic collections don't have indexes') because only indexed collections - List mapped with @OrderColumn/@ListIndexBase and Map with a key - can answer 'at which position does this element sit'. Any operation asking for element indexes against a Set/Bag-mapped role fails here.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/CollectionType.java:70
private final String foreignKeyPropertyName;
// the need for the persister if very hot in many use cases: cache it in a field
// TODO initialize it at constructor time
private volatile CollectionPersister persister;
public CollectionType(String role, String foreignKeyPropertyName) {
this.role = role;
this.foreignKeyPropertyName = foreignKeyPropertyName;
}
public abstract CollectionClassification getCollectionClassification();
public String getRole() {
return role;
}
public Object indexOf(Object collection, Object element) {
throw new UnsupportedOperationException( "generic collections don't have indexes" );
}
public boolean contains(Object collection, Object childObject, SharedSessionContractImplementor session) {
// we do not have to worry about queued additions to uninitialized
// collections, since they can only occur for inverse collections!
final var elems = getElementsIterator( collection );
while ( elems.hasNext() ) {
final Object maybeProxy = elems.next();
// worrying about proxies is perhaps a little bit of overkill here...
final var initializer = extractLazyInitializer( maybeProxy );
final Object element =
initializer != null && !initializer.isUninitialized()
? initializer.getImplementation()
: maybeProxy;
if ( element == childObject ) {
return true;
}
}View on GitHub (pinned to fad1729dce)
Solutions
- If order matters, map the collection as a List with @OrderColumn (or a Map with @MapKeyColumn) so indexes exist.
- If order does not matter, rewrite the query to use element membership/elements instead of index functions.
- Check the persister: for Set-typed roles there is no index by definition - restructure the query or the model.
- Replace legacy 'indices(...)'/'index(...)' HQL with @OrderColumn-based list handling or explicit position columns.
Example fix
// before (lines is Set<Line>)
List<Integer> idx = session.createQuery(
"select index(l) from Order o join o.lines l", Integer.class)
.getResultList(); // UnsupportedOperationException
// after: map as ordered List
@OneToMany(mappedBy = "order")
@OrderColumn(name = "position")
private List<Line> lines = new ArrayList<>();
// then 'select index(l) ...' is valid Defensive patterns
Strategy: validation
Validate before calling
// Before querying, verify the collection actually has an index
CollectionPersister p = ((SessionFactoryImplementor) sessionFactory)
.getMappingMetamodel().getCollectionDescriptor(Order.class.getName() + ".lines");
if (!p.hasIndex()) {
throw new IllegalStateException(
"Order.lines is a Set/Bag; index()/indices() queries are not valid");
} Type guard
static boolean isIndexedCollection(Collection<?> c) {
return c instanceof List<?> || c instanceof Map<?, ?>;
} Prevention
- Map ordered data as List + @OrderColumn or Map + @MapKeyColumn when queries need element positions.
- Remove index()/indices() expressions from HQL the moment a collection becomes a Set.
When it happens
Trigger: HQL that requests the index of elements on a collection mapped as Set or Bag (e.g. 'select index(d.lines) from Order d' or legacy 'indices(...)' where lines is a Set/@ElementCollection without @OrderColumn); programmatic calls to CollectionType.indexOf(collection, element) on a set/bag role; internal paths that build indexed snapshots for a role whose persister is not indexed.
Common situations: Changing a @OneToMany List to Set (for uniqueness) while old queries still use index()/list()-style expressions; porting legacy Hibernate 3/4 HQL that used indices()/elements(); assuming @ElementCollection of an ordered DB collection is index-addressable without @OrderColumn.
Related errors
- Plural path '${getNavigablePath()}' refers to a collection a
- Cannot access the type of plural valued simple paths
- Cannot treat plural valued simple paths
- Illegal null value for list index encountered while reading:
- Insert conflict 'do update' clause with constraint name is n
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/bd2896ad3a8f32d9.
Report an issue: GitHub.