hibernate/hibernate-orm · error · IllegalArgumentException
{} is not an entity
Error message
{} is not an entity What it means
Thrown by PersistenceUnitUtilImpl.getPersister() as an IllegalArgumentException when theSessionFactory's mapping metamodel has no EntityPersister for the given class - i.e. the object passed to PersistenceUnitUtil.getIdentifier()/getVersion() is an instance of a class that is not a mapped entity in this persistence unit. Both the null-persister check and any MappingException during lookup are wrapped in this error.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java:149
}
}
private Object getIdentifierFromPersister(Object entity) {
return getPersister( entity ).getIdentifier( entity );
}
private Object getVersionFromPersister(Object entity) {
return getPersister( entity ).getVersion( entity );
}
private EntityPersister getPersister(Object entity) {
final var entityClass = Hibernate.getClass( entity );
try {
final var entityPersister =
sessionFactory.getMappingMetamodel()
.getEntityDescriptor( entityClass );
if ( entityPersister == null ) {
throw new IllegalArgumentException( entityClass.getName() + " is not an entity" );
}
return entityPersister;
}
catch (MappingException ex) {
throw new IllegalArgumentException( entityClass.getName() + " is not an entity", ex );
}
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Register the class as an entity in the persistence unit (@Entity plus discoverable via scanning or listed in persistence.xml).
- Make sure you call the PersistenceUnitUtil of the EntityManagerFactory that actually maps that class.
- If you pass DTOs, do not route them through getIdentifier/getVersion - carry the id in the DTO explicitly.
- With exclude-unlisted-classes=true, add a <class> entry for every entity.
Example fix
<!-- before --> <persistence-unit name="pu"> <exclude-unlisted-classes>true</exclude-unlisted-classes> <!-- com.acme.Order missing -> getIdentifier(order) throws 'is not an entity' --> </persistence-unit> <!-- after --> <persistence-unit name="pu"> <exclude-unlisted-classes>true</exclude-unlisted-classes> <class>com.acme.Order</class> </persistence-unit>
Defensive patterns
Strategy: type-guard
Validate before calling
// guard before calling PersistenceUnitUtil
if (!emf.getMetamodel().getEntities().stream()
.map(e -> e.getJavaType())
.anyMatch(t -> t.isAssignableFrom(entity.getClass()))) {
throw new IllegalArgumentException(entity.getClass() + " is not mapped in this persistence unit");
} Type guard
boolean isMappedEntity(EntityManagerFactory emf, Class<?> type) {
try { return emf.getMetamodel().entity(type) != null; }
catch (IllegalArgumentException e) { return false; }
} Prevention
- Route only real entities through getIdentifier/getVersion; keep ids inside DTOs explicitly.
- With exclude-unlisted-classes=true, add a <class> entry per entity and test boot of every unit.
- In multi-PU apps, key PersistenceUnitUtil lookups by the same name as the EntityManagerFactory.
When it happens
Trigger: Calling getIdentifier()/getVersion() on a DTO, a plain POJO, a class mapped in a different SessionFactory, or an entity class whose mapping was never added (e.g. not listed in persistence.xml when <exclude-unlisted-classes>true</exclude-unlisted-classes>).
Common situations: Passing projections/DTOs from query results into JPA metadata helpers; multi-persistence-unit apps where the wrong EntityManagerFactory is used; entities living in a jar not scanned because unlisted classes are excluded; test fixtures instantiating unmapped copies of entity classes.
Related errors
- Entity may not be null
- Entity '<entityName>' is not audited
- Entity '<entityName>' is not audited
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/73a45b198b2d541c.
Report an issue: GitHub.