hibernate/hibernate-orm · error · IllegalArgumentException

Not a treatable type: ${treatJavaType.getName()}

Error message

Not a treatable type: ${treatJavaType.getName()}

What it means

SqmMapJoin.treatAs(Class, alias, fetch) downcasts a map join's value type V to a subtype S. It resolves the class via nodeBuilder().getDomainModel().managedType(treatJavaType) and requires the result to implement TreatableDomainType (entities and embeddables do); anything else - typically a @MappedSuperclass - throws IllegalArgumentException 'Not a treatable type: <FQCN>'. The sibling overload treatAs(EntityDomainType, alias, fetch) skips this check entirely because the metamodel type is already trusted.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmMapJoin.java:181

	}

	@Override
	@Nonnull
	public <S extends V> SqmTreatedMapJoin<L, K, V, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias) {
		return treatAs( treatJavaType, alias, false );
	}

	@Override
	@Nonnull
	public <S extends V> SqmTreatedMapJoin<L, K, V, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias, boolean fetch) {
		final var treatTarget = nodeBuilder().getDomainModel().managedType( treatJavaType );
		final var treat = (SqmTreatedMapJoin<L, K, V, S>) findTreat( treatTarget, alias );
		if ( treat == null ) {
			if ( treatTarget instanceof TreatableDomainType<S> ) {
				return addTreat( new SqmTreatedMapJoin<>( this, (SqmTreatableDomainType<S>) treatTarget, alias, fetch ) );
			}
			else {
				throw new IllegalArgumentException( "Not a treatable type: " + treatJavaType.getName() );
			}
		}
		else {
			return treat;
		}
	}

	@Nonnull
	@Override
	public <S extends V> SqmTreatedMapJoin<L, K, V, S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {
		return treatAs( treatTarget, null );
	}

	@Override
	@Nonnull
	public <S extends V> SqmTreatedMapJoin<L, K, V, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias, boolean fetch) {
		final var treat = (SqmTreatedMapJoin<L, K, V, S>) findTreat( treatTarget, alias );
		if ( treat == null ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass a concrete @Entity subtype of the map value type, e.g. mapJoin.treatAs(Cat.class)
  2. Prefer the type-safe overload: mapJoin.treatAs( metamodel.entity( Cat.class ) ) - it bypasses the class-resolution check
  3. Verify the treat target is annotated @Entity (not @MappedSuperclass) and is part of the same persistence unit
  4. If the hierarchy root is a @MappedSuperclass, treat directly to each concrete subclass used in the query

Example fix

// before - Animal is a @MappedSuperclass -> 'Not a treatable type: ...Animal'
SqmTreatedMapJoin<Person, String, Animal, Cat> tj = mapJoin.treatAs( Animal.class );

// after - treat to the concrete @Entity subtype
SqmTreatedMapJoin<Person, String, Animal, Cat> tj = mapJoin.treatAs( Cat.class );
// or, skipping class resolution entirely:
SqmTreatedMapJoin<Person, String, Animal, Cat> tj2 =
        mapJoin.treatAs( metamodel.entity( Cat.class ) );
Defensive patterns

Strategy: validation

Validate before calling

import org.hibernate.metamodel.model.domain.TreatableDomainType;

ManagedType<?> candidate;
try {
    candidate = entityManager.getMetamodel().managedType( treatClass );
} catch ( IllegalArgumentException e ) {
    throw new IllegalArgumentException( "Not a managed type: " + treatClass.getName(), e );
}
if ( !(candidate instanceof TreatableDomainType<?>) ) {
    throw new IllegalArgumentException(
            "Not a treatable type (use a concrete @Entity subtype): " + treatClass.getName() );
}
return mapJoin.treatAs( treatClass );

Type guard

static boolean isTreatableTarget(jakarta.persistence.metamodel.Metamodel mm, Class<?> c) {
    try {
        return mm.managedType( c ) instanceof org.hibernate.metamodel.model.domain.TreatableDomainType<?>;
    } catch ( IllegalArgumentException e ) {
        return false; // not managed at all
    }
}

Try / catch

try {
    join = mapJoin.treatAs( treatClass );
} catch ( IllegalArgumentException e ) {
    if ( e.getMessage() != null && e.getMessage().startsWith( "Not a treatable type" ) ) {
        throw new IllegalArgumentException( "Treat target " + treatClass.getName()
                + " is not an @Entity/@Embeddable in this persistence unit", e );
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling mapJoin.treatAs(SubType.class) or mapJoin(SubType.class) (HQL `join treat(x.map as Sub)` routes here too) where SubType resolves to a managed type that is not treatable - a @MappedSuperclass base class, or a class not mapped as @Entity/@Embeddable in this persistence unit.

Common situations: Treating a Map<String, Animal> join to Animal where Animal is a @MappedSuperclass rather than a mapped entity; wrong import using an identically named unmapped class; entity classes live in a module not included in the persistence unit; embeddable-valued maps treated against non-embeddable subtypes.

Related errors


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