{"record":{"id":"bd5ab5ef5a3e66ad","repo":"hibernate/hibernate-orm","slug":"not-a-treatable-type-bd5ab5","errorCode":null,"errorMessage":"Not a treatable type: {}","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/SqmSingularJoin.java","lineNumber":133,"sourceCode":"\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <S extends T> SqmTreatedAttributeJoin<O, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {\n\t\treturn treatAs( treatTarget, alias, false );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <S extends T> SqmTreatedSingularJoin<O,T,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 = (SqmTreatedSingularJoin<O, T, S>) findTreat( treatTarget, alias );\n\t\tif ( treat == null ) {\n\t\t\tif ( treatTarget instanceof SqmTreatableDomainType<S> treatableDomainType ) {\n\t\t\t\treturn addTreat( new SqmTreatedSingularJoin<>( this, treatableDomainType, 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\telse {\n\t\t\treturn treat;\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias, boolean fetch) {\n\t\tfinal var treat = (SqmTreatedSingularJoin<O, T, S>) findTreat( treatTarget, alias );\n\t\tif ( treat == null ) {\n\t\t\treturn addTreat( new SqmTreatedSingularJoin<>( this, (SqmEntityDomainType<S>) treatTarget, alias, fetch ) );\n\t\t}\n\t\telse {\n\t\t\treturn treat;\n\t\t}\n\t}","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmSingularJoin.java#L115-L151","documentation":"The singular-join variant of TREAT: treatAs(Class) resolves the requested Java type via managedType(...), and only proceeds when the result is a SqmTreatableDomainType. Interfaces resolved to a polymorphic grouping descriptor, embeddables, and unmapped classes fail that check and Hibernate throws IllegalArgumentException 'Not a treatable type: <class name>'.","triggerScenarios":"singularJoin.treatAs(SomeInterface.class) or root.<X>join(\"attr\", jt).treatAs(X.class) where X is not a mapped entity; treating a many-to-one whose target is polymorphic to an interface instead of a concrete entity; treatAs with a class the persistence unit does not contain.","commonSituations":"Criteria queries that downcast association paths via TREAT; model refactors that turned the treat target into an interface or moved it out of the persistence unit; upgrading Hibernate versions where treat target validation moved to SQM construction time.","solutions":["Use a concrete mapped entity subtype as the treat target.","Pre-validate with metamodel.entity(targetClass) (throws IllegalArgumentException 'not an entity' for unmapped types) before calling treatAs.","For interface targets, run one query per implementor and union results, or filter rows in Java with instanceof.","Pass the already-resolved EntityDomainType via treatAs(EntityDomainType) instead of the Class overload."],"exampleFix":"// before\nJpaJoin<Order, BillingDetails> j = (JpaJoin<Order, BillingDetails>) root.join(\"detail\");\nj.treatAs(BillingDetails.class); // BillingDetails is an interface -> Not a treatable type\n// after\nj.treatAs(CreditCardPayment.class); // mapped entity subtype\n// or pre-resolve:\nEntityDomainType<CreditCardPayment> t = sf.getJpaMetamodel().entity(CreditCardPayment.class);\nj.treatAs(t, \"cc\");","handlingStrategy":"validation","validationCode":"static boolean isTreatableTarget(EntityManagerFactory emf, Class<?> joinedType, Class<?> target) {\n    try {\n        emf.getMetamodel().entity(target); // must be a mapped entity, not interface/embeddable\n        return joinedType.isAssignableFrom(target);\n    } catch (IllegalArgumentException notMapped) {\n        return false;\n    }\n}","typeGuard":"static boolean treatable(EntityManagerFactory emf, Class<?> target) {\n    try { emf.getMetamodel().entity(target); return true; }\n    catch (IllegalArgumentException e) { return false; }\n}","tryCatchPattern":"try {\n    treated = singularJoin.treatAs(targetClass);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Not a treatable type\")) {\n        treated = null; // fall back to instanceof filtering in Java\n    } else throw e;\n}","preventionTips":["Validate treat targets against the metamodel before building the query.","Use the treatAs(EntityDomainType, alias, fetch) overload with a pre-resolved entity type.","After refactors, verify @Entity annotations on treat targets are still present and scanned."],"tags":["hibernate","criteria-api","treat","jpa-metamodel","illegal-argument","downcasting"],"backgroundTag":"invalid-treat-target","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}