hibernate/hibernate-orm · error · NotIndexedCollectionException
Index operator applied to path '${getNavigablePath()}' which
Error message
Index operator applied to path '${getNavigablePath()}' which is not a list or map What it means
The HQL index operator 'path[selector]' is only defined for indexed collections. SqmPluralValuedSimplePath.resolveIndexedAccess handles exactly two shapes: a ListPersistentAttribute (selector compared to the list position) and a MapPersistentAttribute (selector compared to the key), building a join with an equality predicate on the index/key. For any other plural attribute (Set, bag/Collection, @ElementCollection without index) there is nothing to compare the selector against, so it throws org.hibernate.query.NotIndexedCollectionException.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmPluralValuedSimplePath.java:208
SqmJoinType.INNER,
false,
nodeBuilder()
);
index = ( (SqmListJoin<?, ?>) join).index();
}
else if ( referencedPathSource instanceof MapPersistentAttribute<?, ?, ?> ) {
join = new SqmMapJoin<>(
parent,
(SqmMapPersistentAttribute<P, ?, ?>) referencedPathSource,
alias,
SqmJoinType.INNER,
false,
nodeBuilder()
);
index = ( (SqmMapJoin<?, ?, ?>) join).key();
}
else {
throw new NotIndexedCollectionException( "Index operator applied to path '" + getNavigablePath()
+ "' which is not a list or map" );
}
join.setJoinPredicate( nodeBuilder().equal( index, selector ) );
parent.addSqmJoin( join );
return join;
}
@Nonnull
@Override
public SqmExpression<Class<? extends C>> type() {
throw new UnsupportedOperationException( "Cannot access the type of plural valued simple paths" );
}
@Nonnull
@Override
public <S extends C> SqmTreatedPath<C, S> treatAs(@Nonnull Class<S> treatJavaType) {
throw new UnsupportedOperationException( "Cannot treat plural valued simple paths" );
}View on GitHub (pinned to fad1729dce)
Solutions
- Rewrite the access as an explicit join with a WHERE on the distinguishing property: 'join p.phones ph where ph.type = "home"'
- If positional access is required, remap as an ordered List with @OrderColumn so 'p.items[0]' is legal
- If keyed access is required, remap as a Map with @MapKey/@MapKeyColumn and use 'p.phones["home"]'
- For bag semantics, filter with a subquery instead of indexing
Example fix
// before: phones mapped as Set<Phone>; HQL uses a key // select p from Person p where p.phones['home'].number = '555-1234' // after: join and filter on the discriminator-like property select p from Person p join p.phones ph where ph.type = 'home' and ph.number = '555-1234' // alternative: remap as a Map so indexing is valid @OneToMany(mappedBy = "person") @MapKeyColumn(name = "phone_type") Map<String, Phone> phones;
Defensive patterns
Strategy: type-guard
Validate before calling
Attribute<?, ?> a = managedType.getAttribute(attrName);
boolean indexable = a instanceof jakarta.persistence.metamodel.ListAttribute<?, ?>
|| a instanceof jakarta.persistence.metamodel.MapAttribute<?, ?, ?>;
if (!indexable) throw new IllegalArgumentException(attrName + " is not a List or Map; [ ] access invalid"); Type guard
static boolean supportsIndexOperator(ManagedType<?> type, String attr) {
Attribute<?, ?> a = type.getAttribute(attr);
return a instanceof jakarta.persistence.metamodel.ListAttribute<?, ?>
|| a instanceof jakarta.persistence.metamodel.MapAttribute<?, ?, ?>;
} Try / catch
try {
return session.createQuery(hql, type).singleResult();
} catch (org.hibernate.query.NotIndexedCollectionException e) {
// rewrite as join + where on the position/key property instead
} Prevention
- Use the [ ] operator only on @OrderColumn lists and @MapKey maps
- Add mapping tests asserting the collection kind every indexed query relies on
- Prefer explicit joins over positional access for Set/bag collections
When it happens
Trigger: HQL 'o.items[0]' or 'p.phones["home"]' where the attribute is a Set<?> or Collection<?>; criteria/SPI indexed access (resolveIndexedAccess) on a non-indexed plural path; mapping the field as Set while the query was written for a List or Map.
Common situations: Changing a field between List/Set/Map without updating queries; adding @ElementCollection as a Set but writing positional access; assuming @OrderColumn exists when the collection was mapped unordered.
Related errors
- Entity discriminator cannot be de-referenced
- Entity discriminator cannot be de-referenced
- Could not resolve attribute '%s' of '%s' due to the attribut
- The function {name} is not an aggregate function
- The function {name} is not an ordered set-aggregate function
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/23fe01de1da5d420.
Report an issue: GitHub.