hibernate/hibernate-orm · error · ClassCastException
Cannot cast to entity type '{}'
Error message
Cannot cast to entity type '{}' What it means
When a query argument is bound against an entity-typed parameter, QueryArguments special-cases Hibernate proxies (isInstance) but otherwise requires the value to be an instance of the entity's Java class. A value of any other class produces ClassCastException with the message 'Cannot cast to entity type <FQCN>'. This is Hibernate's entity-argument conversion path, not a bad cast in user code.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/QueryArguments.java:119
public static <T> T cast(Object value, JavaType<T> javaType) {
if ( value == null ) {
return null;
}
else if ( javaType instanceof EntityJavaType<?> ) {
// special handling for entity arguments due to
// the possibility of an uninitialized proxy
// (which we don't want or need to fetch)
if ( isInstance( value, javaType ) ) {
// The proxy might not literally be an
// instance of the entity class represented
// by the unreified type T, but it is an
// instance in spirit
//noinspection unchecked
return (T) value;
}
else {
throw new ClassCastException( "Cannot cast to entity type '"
+ javaType.getJavaTypeClass().getTypeName() + "'" );
}
}
else {
// require that the argument be assignable to the parameter
return javaType.cast( javaType.coerce( value ) );
}
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Pass an instance of the exact entity class the comparison expects.
- Compare by identifier instead: 'where o.customer.id = :cid' and bind customer.getId().
- When types are uncertain, inspect query.getParameterMetadata().getQueryParameter(name).getParameterType() before binding.
Example fix
// before
var q = session.createQuery("from Order o where o.customer = :c", Order.class);
q.setParameter("c", someVendor); // Vendor is not Customer -> ClassCastException
// after
q.setParameter("c", customer);
// or compare by id:
var q2 = session.createQuery("from Order o where o.customer.id = :cid", Order.class);
q2.setParameter("cid", customer.getId()); Defensive patterns
Strategy: type-guard
Validate before calling
static void bindEntity(org.hibernate.query.Query<?> q, String name, Object value, Class<?> entityJavaType) {
Object unwrapped = org.hibernate.Hibernate.unproxy(value);
if (unwrapped != null && !entityJavaType.isInstance(unwrapped))
throw new IllegalArgumentException("Expected " + entityJavaType.getSimpleName()
+ " but got " + unwrapped.getClass().getSimpleName());
q.setParameter(name, value);
} Type guard
static boolean isEntityInstance(Object value, Class<?> entityJavaType) {
return value == null || entityJavaType.isInstance(org.hibernate.Hibernate.unproxy(value));
} Prevention
- Compare by foreign key id instead of entity instance where possible.
- Avoid passing entities through generic Map<String,Object> contexts.
- Type the repository layer so the compiler catches entity mix-ups.
When it happens
Trigger: setParameter("c", value) on a query like "from Order o where o.customer = :c" where value is an instance of a different entity class (e.g. Vendor instead of Customer), or a DTO/Map passed where the mapped entity is expected.
Common situations: Similar domain classes or inheritance hierarchies where the wrong subtype flows through generic code; values arriving from generic Map<String,Object> request contexts; refactors that changed an entity type while callers still pass the old one.
Related errors
- jakarta.persistence.validation.group.{} is of unknown type:
- Given object was not an instance of {} [{}]
- Configuration property hibernate.jdbc.time_zone value [{}] i
- Configuration property hibernate.order_by.default_null_order
- Wrong kind of binder for annotation type: '%s' does not acce
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/70ea12cb226809a7.
Report an issue: GitHub.