{"record":{"id":"23fe01de1da5d420","repo":"hibernate/hibernate-orm","slug":"index-operator-applied-to-path-getnavigablepath","errorCode":null,"errorMessage":"Index operator applied to path '${getNavigablePath()}' which is not a list or map","messagePattern":"Index operator applied to path '(.+?)' which is not a list or map","errorType":"exception","errorClass":"NotIndexedCollectionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmPluralValuedSimplePath.java","lineNumber":208,"sourceCode":"\t\t\t\t\tSqmJoinType.INNER,\n\t\t\t\t\tfalse,\n\t\t\t\t\tnodeBuilder()\n\t\t\t);\n\t\t\tindex = ( (SqmListJoin<?, ?>) join).index();\n\t\t}\n\t\telse if ( referencedPathSource instanceof MapPersistentAttribute<?, ?, ?> ) {\n\t\t\tjoin = new SqmMapJoin<>(\n\t\t\t\t\tparent,\n\t\t\t\t\t(SqmMapPersistentAttribute<P, ?, ?>) referencedPathSource,\n\t\t\t\t\talias,\n\t\t\t\t\tSqmJoinType.INNER,\n\t\t\t\t\tfalse,\n\t\t\t\t\tnodeBuilder()\n\t\t\t);\n\t\t\tindex = ( (SqmMapJoin<?, ?, ?>) join).key();\n\t\t}\n\t\telse {\n\t\t\tthrow new NotIndexedCollectionException( \"Index operator applied to path '\" + getNavigablePath()\n\t\t\t\t\t+ \"' which is not a list or map\" );\n\t\t}\n\t\tjoin.setJoinPredicate( nodeBuilder().equal( index, selector ) );\n\t\tparent.addSqmJoin( join );\n\t\treturn join;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmExpression<Class<? extends C>> type() {\n\t\tthrow new UnsupportedOperationException( \"Cannot access the type of plural valued simple paths\" );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <S extends C> SqmTreatedPath<C, S> treatAs(@Nonnull Class<S> treatJavaType) {\n\t\tthrow new UnsupportedOperationException( \"Cannot treat plural valued simple paths\" );\n\t}","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmPluralValuedSimplePath.java#L190-L226","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: phones mapped as Set<Phone>; HQL uses a key\n// select p from Person p where p.phones['home'].number = '555-1234'\n\n// after: join and filter on the discriminator-like property\nselect p from Person p join p.phones ph where ph.type = 'home' and ph.number = '555-1234'\n\n// alternative: remap as a Map so indexing is valid\n@OneToMany(mappedBy = \"person\")\n@MapKeyColumn(name = \"phone_type\")\nMap<String, Phone> phones;","handlingStrategy":"type-guard","validationCode":"Attribute<?, ?> a = managedType.getAttribute(attrName);\nboolean indexable = a instanceof jakarta.persistence.metamodel.ListAttribute<?, ?>\n    || a instanceof jakarta.persistence.metamodel.MapAttribute<?, ?, ?>;\nif (!indexable) throw new IllegalArgumentException(attrName + \" is not a List or Map; [ ] access invalid\");","typeGuard":"static boolean supportsIndexOperator(ManagedType<?> type, String attr) {\n    Attribute<?, ?> a = type.getAttribute(attr);\n    return a instanceof jakarta.persistence.metamodel.ListAttribute<?, ?>\n        || a instanceof jakarta.persistence.metamodel.MapAttribute<?, ?, ?>;\n}","tryCatchPattern":"try {\n    return session.createQuery(hql, type).singleResult();\n} catch (org.hibernate.query.NotIndexedCollectionException e) {\n    // rewrite as join + where on the position/key property instead\n}","preventionTips":["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"],"tags":["hibernate","hql","sqm","collection-index","set-vs-list","notindexedcollectionexception"],"backgroundTag":"indexed-access-non-indexed-collection","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}