hibernate/hibernate-orm · error · IllegalStateException
Entity '{name}' does not have a natural id
Error message
Entity '{name}' does not have a natural id What it means
BaseEntityPersister.isNaturalIdentifierInsertGenerated() answers whether any natural-id property is generated during INSERT execution; it assumes the entity has a natural id and throws IllegalStateException('Entity ... does not have a natural id') when naturalIdPropertyNumbers is empty. It is a persister capability probe reached from insert/natural-id handling paths, not a user query API, so hitting it usually means generic code probed an entity that has no @NaturalId properties.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/persister/entity/BaseEntityPersister.java:631
private void mapPropertyToIndex(Property property, int i) {
propertyIndexes.put( property.getName(), i );
if ( property.getValue() instanceof Component composite ) {
for ( var subproperty : composite.getProperties() ) {
propertyIndexes.put(
property.getName() + '.' + subproperty.getName(),
i
);
}
}
}
/**
* @return {@code true} if one of the properties belonging to the natural id
* is generated during the execution of an {@code insert} statement
*/
public boolean isNaturalIdentifierInsertGenerated() {
if ( naturalIdPropertyNumbers.length == 0 ) {
throw new IllegalStateException( "Entity '" + name + "' does not have a natural id" );
}
for ( int naturalIdPropertyNumber : naturalIdPropertyNumbers ) {
final var strategy = generators[naturalIdPropertyNumber];
if ( strategy != null
&& strategy.generatesOnInsert()
&& strategy.generatedOnExecution() ) {
return true;
}
}
return false;
}
public int[] getNaturalIdentifierProperties() {
return naturalIdPropertyNumbers;
}
public boolean hasNaturalIdentifier() {
return naturalIdPropertyNumbers!=null;View on GitHub (pinned to fad1729dce)
Solutions
- Guard every call with EntityPersister.hasNaturalIdentifier() before probing
- Define @NaturalId on the entity if it is supposed to have one
- Fix generic framework code to skip entities without natural ids
Example fix
// before
boolean generated = persister.isNaturalIdentifierInsertGenerated(); // throws if no natural id
// after
boolean generated = persister.hasNaturalIdentifier()
&& persister.isNaturalIdentifierInsertGenerated(); Defensive patterns
Strategy: validation
Validate before calling
EntityPersister p = sessionFactory.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor(User.class);
boolean generated = p.hasNaturalIdentifier()
&& p.isNaturalIdentifierInsertGenerated(); Prevention
- Always pair capability probes with hasNaturalIdentifier() in generic framework code
- Keep an inventory of which entities have @NaturalId when adding natural-id caching or post-insert hooks
- Write one unit test per framework probe that runs it over an entity without a natural id
When it happens
Trigger: Calling EntityPersister.isNaturalIdentifierInsertGenerated() (directly, or via framework/session-internal code that updates the natural-id region after insert) on an entity with no @NaturalId; generic scaffolding that iterates all persisters and probes this capability unconditionally.
Common situations: Generic DAO/audit/multi-tenant frameworks probing every persister; enabling natural-id caching globally while some entities lack natural ids; removing a base-class @NaturalId during refactoring while framework code still probes it.
Related errors
- EntityPersister implementation '{className}' does not suppor
- EntityPersister implementation '{className}' does not suppor
- No fetch profile named '{}'
- Same column is added more than once with different values fo
- Same column is added more than once with different values fo
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/5165ee28089b11d7.
Report an issue: GitHub.