hibernate/hibernate-orm · error · IllegalArgumentException
Not a treatable type: {}
Error message
Not a treatable type: {} What it means
treatAs(Class) on a set join resolves the target Java type through the domain model with managedType(treatJavaType), then only accepts the treat if the resolved type is a TreatableDomainType (an entity or, in newer versions, a mapped superclass). If the class resolves to anything else — an interface grouping (polymorphic descriptor), an @Embeddable, or an unmapped class — Hibernate throws IllegalArgumentException naming the offending class.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmSetJoin.java:170
}
@Override
@Nonnull
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {
return treatAs( treatTarget, alias, false );
}
@Override
@Nonnull
public <S extends E> SqmTreatedSetJoin<O, E, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias, boolean fetch) {
final var treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
final var treat = (SqmTreatedSetJoin<O, E, S>) findTreat( treatTarget, alias );
if ( treat == null ) {
if ( treatTarget instanceof TreatableDomainType<?> ) {
return addTreat( new SqmTreatedSetJoin<>( this, (SqmTreatableDomainType<S>) treatTarget, alias, fetch ) );
}
else {
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
}
}
else {
return treat;
}
}
@Override
@Nonnull
public <S extends E> SqmTreatedSetJoin<O,E,S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias, boolean fetch) {
final var treat = (SqmTreatedSetJoin<O, E, S>) findTreat( treatTarget, alias );
if ( treat == null ) {
return addTreat( new SqmTreatedSetJoin<>( this, (SqmEntityDomainType<S>) treatTarget, alias, fetch ) );
}
else {
return treat;
}
}View on GitHub (pinned to fad1729dce)
Solutions
- Treat to a concrete @Entity subtype of the joined element type: join.treat(CreditCardPayment.class).
- Verify the target is mapped: metamodel.entity(target) must succeed (and be a subtype of the join element type) before calling treat.
- If the target is an interface, treat each implementor separately or drop the treat and rely on implicit polymorphism with instanceof filtering.
- Use the treatAs(EntityDomainType) overload after resolving metamodel.entity(target) so mapping errors surface earlier and clearer.
Example fix
// before
SetJoin<Order, BillingDetails> details = root.joinSet("billingDetails");
details.treat(OnlinePayment.class); // OnlinePayment is an interface -> Not a treatable type
// after
details.treat(CreditCardPayment.class); // concrete @Entity subtype
// or resolve first:
EntityDomainType<CreditCardPayment> target = sf.getJpaMetamodel().entity(CreditCardPayment.class);
details.treatAs(target); Defensive patterns
Strategy: validation
Validate before calling
static boolean isTreatableTarget(EntityManagerFactory emf, Class<?> joinedType, Class<?> target) {
try {
jakarta.persistence.metamodel.EntityType<?> e = emf.getMetamodel().entity(target); // real entity only
return joinedType.isAssignableFrom(target);
} catch (IllegalArgumentException notMapped) {
return false; // interface/embeddable/unmapped -> treat would throw
}
} Type guard
static boolean treatable(EntityManagerFactory emf, Class<?> target) {
try { emf.getMetamodel().entity(target); return true; }
catch (IllegalArgumentException e) { return false; }
} Try / catch
try {
treated = setJoin.treat(targetClass);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Not a treatable type")) {
// fall back: query concrete implementors separately
} else throw e;
} Prevention
- Treat only to concrete @Entity subtypes of the joined element type.
- Pre-resolve targets with metamodel.entity(...) and pass the EntityDomainType overload of treatAs.
- Keep a startup check that validates all treat targets used by query builders.
- For interface targets, write one query per implementor and union results.
When it happens
Trigger: Calling setJoin.treat(SomeInterface.class) where SomeInterface is implemented by several entities (managedType returns SqmPolymorphicRootDescriptor, not treatable); treating to an @Embeddable target; treating to a class not included in the persistence unit.
Common situations: Criteria/HQL TREAT on collection joins whose element type is an interface; refactors where the treat target stopped being an @Entity (annotation lost, class moved to another module); typo'd or unmapped subclass names in treatAs.
Related errors
- Not a treatable type: {}
- Illegal call to IdentifiableType#getId for class [{}] define
- This class [{}] does not define an IdClass
- The version attribute is not declared or inherited by this t
- Unable to locate %s with the given name [%s] on this Managed
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/6327c5721408e98a.
Report an issue: GitHub.