{"record":{"id":"b7e702d605e56fd8","repo":"hibernate/hibernate-orm","slug":"not-a-treatable-type-treatjavatype-getname","errorCode":null,"errorMessage":"Not a treatable type: {treatJavaType.getName()}","messagePattern":"Not a treatable type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBagJoin.java","lineNumber":169,"sourceCode":"\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {\n\t\treturn treatAs( treatTarget, alias, false );\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <S extends E> SqmTreatedBagJoin<O, E, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias, boolean fetch) {\n\t\tfinal var treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );\n\t\tfinal var treat = (SqmTreatedBagJoin<O, E, S>) findTreat( treatTarget, alias );\n\t\tif ( treat == null ) {\n\t\t\tif ( treatTarget instanceof TreatableDomainType<?> ) {\n\t\t\t\treturn addTreat( new SqmTreatedBagJoin<>( this, (SqmTreatableDomainType<S>) treatTarget, alias, fetch ) );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new IllegalArgumentException( \"Not a treatable type: \" + treatJavaType.getName() );\n\t\t\t}\n\t\t}\n\t\treturn treat;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <S extends E> SqmTreatedBagJoin<O,E,S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias, boolean fetch) {\n\t\tfinal var treat = (SqmTreatedBagJoin<O, E, S>) findTreat( treatTarget, alias );\n\t\tif ( treat == null ) {\n\t\t\treturn addTreat( new SqmTreatedBagJoin<>( this, (SqmEntityDomainType<S>) treatTarget, alias, fetch ) );\n\t\t}\n\t\telse {\n\t\t\treturn treat;\n\t\t}\n\t}\n\n}","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBagJoin.java#L151-L187","documentation":"SqmBagJoin.treatAs(Class, String alias, boolean fetch) (SqmBagJoin.java:161-173) resolves the passed class against the domain model via nodeBuilder().getDomainModel().managedType(treatJavaType) and requires the result to implement TreatableDomainType; entity types (and embeddable types in this codebase) implement it, while mapped-superclass types do not. When the class resolves to a managed but non-treatable type it throws IllegalArgumentException('Not a treatable type: <FQCN>') — the requested downcast target cannot be the right-hand side of a TREAT. All shorter Class-based overloads on SqmBagJoin (treat(Class), treatAs(Class), treatAs(Class, alias)) delegate to this method, so each fails identically; note the HQL 'treat(b as Sub)' route uses the EntityDomainType overload (line 175+) which does not perform this check.","triggerScenarios":"Calling bagJoin.treat(AbstractBase.class) / treatAs(...) on a List/Collection-valued join where AbstractBase is a @MappedSuperclass of the element type — managedType() resolves it to a MappedSuperclassDomainType which does not extend TreatableDomainType, so the check at line 165 fails. Also triggered by passing an embeddable class on Hibernate versions where EmbeddableDomainType is not treatable, or by generic frameworks accepting arbitrary Class tokens as treat targets. Only the Class-based overloads reach this line.","commonSituations":"Downcasting a @OneToMany List to a shared abstract base that is mapped as @MappedSuperclass instead of an @Entity hierarchy node; treating collections of embeddables; query frameworks that let callers pass any Class for treat; refactorings where a base class was annotated @MappedSuperclass and queries still treat to it.","solutions":["Pass a concrete @Entity subtype of the element type as the treat target — mapped superclasses are not treatable because they have no table or discriminator.","Validate first: resolve the target with domainModel.entity(SubType.class) or check managedType(...) instanceof TreatableDomainType before calling treatAs.","If the abstract base must be a treat target, map it as an @Entity in the inheritance hierarchy (with an inheritance strategy) instead of @MappedSuperclass.","Prefer the EntityDomainType overload treatAs(domainModel.entity(Sub.class), alias, fetch), which fails earlier and with a clearer error for wrong classes."],"exampleFix":"// before - BaseLine is a @MappedSuperclass of order lines\nListJoin<Order, Line> lines = root.join(Order_.lines, JoinType.INNER);\nlines.treat(BaseLine.class, \"bl\", false); // IllegalArgumentException: Not a treatable type: ...BaseLine\n\n// after - treat to a concrete @Entity subtype\nlines.treat(BookLine.class, \"bl\", false); // BookLine is an @Entity extending BaseLine","handlingStrategy":"validation","validationCode":"import org.hibernate.metamodel.model.domain.ManagedDomainType;\nimport org.hibernate.metamodel.model.domain.TreatableDomainType;\n\nJpaMetamodel metamodel = sessionFactory.getDomainModel();\nManagedDomainType<?> target = metamodel.managedType(SubType.class);\nif (!(target instanceof TreatableDomainType)) {\n    throw new IllegalArgumentException(\n        SubType.class.getName() + \" is not treatable (must be an entity subtype, not a @MappedSuperclass)\");\n}\nbagJoin.treatAs(SubType.class, \"t\", false);","typeGuard":"static boolean isTreatableType(JpaMetamodel metamodel, Class<?> candidate) {\n    try {\n        return metamodel.managedType(candidate) instanceof TreatableDomainType<?>;\n    } catch (IllegalArgumentException e) {\n        return false; // not a managed type at all\n    }\n}","tryCatchPattern":"try {\n    join.treatAs(SubType.class, alias, fetch);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Not a treatable type\")) {\n        // treat target resolved to a non-treatable managed type (e.g. @MappedSuperclass)\n        throw new QueryBuildException(\"TREAT target must be an @Entity subtype: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Only TREAT to concrete @Entity subtypes of the joined element type.","Never pass @MappedSuperclass (or embeddable) classes as treat targets.","Resolve treat targets once via domainModel.entity(SubType.class) and use the EntityDomainType overloads — wrong classes fail earlier and clearer.","In generic frameworks, validate candidate classes with instanceof TreatableDomainType before calling treatAs."],"tags":["hibernate","sqm","treat","bag-join","mapped-superclass","jpa-criteria","illegal-argument"],"backgroundTag":"treat-on-non-entity-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}