hibernate/hibernate-orm · error · IllegalArgumentException
Not a treatable type: {}
Error message
Not a treatable type: {} What it means
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>'.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmSingularJoin.java:133
}
@Nonnull
@Override
public <S extends T> SqmTreatedAttributeJoin<O, T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {
return treatAs( treatTarget, alias, false );
}
@Nonnull
@Override
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias, boolean fetch) {
final var treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
final var treat = (SqmTreatedSingularJoin<O, T, S>) findTreat( treatTarget, alias );
if ( treat == null ) {
if ( treatTarget instanceof SqmTreatableDomainType<S> treatableDomainType ) {
return addTreat( new SqmTreatedSingularJoin<>( this, treatableDomainType, alias, fetch ) );
}
else {
throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
}
}
else {
return treat;
}
}
@Override
@Nonnull
public <S extends T> SqmTreatedSingularJoin<O,T,S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias, boolean fetch) {
final var treat = (SqmTreatedSingularJoin<O, T, S>) findTreat( treatTarget, alias );
if ( treat == null ) {
return addTreat( new SqmTreatedSingularJoin<>( this, (SqmEntityDomainType<S>) treatTarget, alias, fetch ) );
}
else {
return treat;
}
}View on GitHub (pinned to fad1729dce)
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.
Example fix
// before
JpaJoin<Order, BillingDetails> j = (JpaJoin<Order, BillingDetails>) root.join("detail");
j.treatAs(BillingDetails.class); // BillingDetails is an interface -> Not a treatable type
// after
j.treatAs(CreditCardPayment.class); // mapped entity subtype
// or pre-resolve:
EntityDomainType<CreditCardPayment> t = sf.getJpaMetamodel().entity(CreditCardPayment.class);
j.treatAs(t, "cc"); Defensive patterns
Strategy: validation
Validate before calling
static boolean isTreatableTarget(EntityManagerFactory emf, Class<?> joinedType, Class<?> target) {
try {
emf.getMetamodel().entity(target); // must be a mapped entity, not interface/embeddable
return joinedType.isAssignableFrom(target);
} catch (IllegalArgumentException notMapped) {
return false;
}
} 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 = singularJoin.treatAs(targetClass);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Not a treatable type")) {
treated = null; // fall back to instanceof filtering in Java
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
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/bd5ab5ef5a3e66ad.
Report an issue: GitHub.