{"record":{"id":"733bcb34f0cf9b2e","repo":"hibernate/hibernate-orm","slug":"cannot-treat-plural-valued-simple-paths","errorCode":null,"errorMessage":"Cannot treat plural valued simple paths","messagePattern":"Cannot treat plural valued simple paths","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmPluralValuedSimplePath.java","lineNumber":225,"sourceCode":"\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}\n\n\t@Nonnull\n\t@Override\n\tpublic <S extends C> SqmTreatedEntityValuedSimplePath<C, S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {\n\t\tthrow new UnsupportedOperationException( \"Cannot treat plural valued simple paths\" );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmPredicate isEmpty() {\n\t\treturn new SqmEmptinessPredicate( this, false, nodeBuilder() );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SqmPredicate isNotEmpty() {\n\t\treturn new SqmEmptinessPredicate( this, true, nodeBuilder() );","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmPluralValuedSimplePath.java#L207-L243","documentation":"The TREAT operator downcasts a path to an entity subtype and is only defined for entity-valued paths. SqmPluralValuedSimplePath.treatAs(Class) throws UnsupportedOperationException because treating the collection reference itself, rather than one of its elements, has no defined semantics in the SQM model. The treat must be applied to a joined element or to element() of the plural path.","triggerScenarios":"HQL 'treat(p.orders as SpecialOrder).bonus > 0' without joining 'orders' first; criteria code calling cb.treat(path.get(\"orders\"), SpecialOrder.class) directly on a plural path; any treatAs(Class) invocation on a path resolved to a @OneToMany/@ManyToMany/@ElementCollection attribute.","commonSituations":"Polymorphic collections where a subtype-specific attribute must be filtered or selected; refactoring a query that used a join alias into inline navigation and forgetting the treat target changed; porting JPQL treat usage from entity paths to collection paths.","solutions":["Join the collection and treat the join alias in HQL: 'from Person p join treat(p.orders as SpecialOrder) so where so.bonus > 0'","In criteria API, join first and treat the Join object: Join<Order,Order> o = p.join(\"orders\"); Join<Order,SpecialOrder> t = cb.treat(o, SpecialOrder.class);","Filter by type and join the subtype association separately: 'join p.orders so where type(so) = SpecialOrder and so.bonus > 0'","If every element is the subtype, change the association target type in the mapping instead of treating at query time"],"exampleFix":"// before (HQL)\nselect p from Person p where treat(p.orders as SpecialOrder).bonus > 0\n\n// after\nselect p from Person p join treat(p.orders as SpecialOrder) so where so.bonus > 0","handlingStrategy":"type-guard","validationCode":"if (path.getReferencedPathSource() instanceof org.hibernate.metamodel.model.domain.PluralPersistentAttribute<?, ?, ?>) {\n    throw new IllegalArgumentException(\"Join the collection before TREAT: \" + path.getNavigablePath());\n}","typeGuard":"static boolean isTreatable(SqmPath<?> path) {\n    return !(path.getReferencedPathSource()\n        instanceof org.hibernate.metamodel.model.domain.PluralPersistentAttribute<?, ?, ?>);\n}","tryCatchPattern":"try {\n    treated = builder.treat(path, SubType.class);\n} catch (UnsupportedOperationException e) {\n    // plural path: join first, then treat the Join object\n}","preventionTips":["Write TREAT against a join alias ('join treat(p.x as T) a'), never against an inline collection path","In criteria API, treat Join objects, not attribute Path objects","Add a query review checklist item: every treat target must be entity-valued"],"tags":["hibernate","hql","sqm","criteria-api","treat","downcast","collection-mapping"],"backgroundTag":"treat-on-non-entity-path","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}