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

  1. Use a concrete mapped entity subtype as the treat target.
  2. Pre-validate with metamodel.entity(targetClass) (throws IllegalArgumentException 'not an entity' for unmapped types) before calling treatAs.
  3. For interface targets, run one query per implementor and union results, or filter rows in Java with instanceof.
  4. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/bd5ab5ef5a3e66ad. Report an issue: GitHub.