hibernate/hibernate-orm · error · IllegalStateException
Retrieved key was null, but to-one is not nullable : %s
Error message
Retrieved key was null, but to-one is not nullable : %s
What it means
While applying follow-on table-lock results, TableLock.ToOneResultHandler reads the FK key value for a to-one association. If the database returned null but the mapping declares the association non-nullable (@ManyToOne(optional=false), @JoinColumn(nullable=false), or a mandatory FK), it throws IllegalStateException with the attribute's full navigable path. The mapping and the stored data disagree.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/exec/internal/lock/TableLock.java:314
applyModelState( entityDetails, statePosition, stateValue );
}
}
// Used by Hibernate Reactive
protected static class ToOneResultHandler extends AbstractResultHandler {
protected final ToOneAttributeMapping toOne;
public ToOneResultHandler(Integer statePosition, ToOneAttributeMapping toOne) {
super( statePosition );
this.toOne = toOne;
}
@Override
public void applyResult(Object stateValue, EntityDetails entityDetails, SharedSessionContractImplementor session) {
final Object reference;
if ( stateValue == null ) {
if ( !toOne.isNullable() ) {
throw new IllegalStateException( "Retrieved key was null, but to-one is not nullable : " + toOne.getNavigableRole().getFullPath() );
}
else {
reference = null;
}
}
else {
reference = session.internalLoad(
toOne.getAssociatedEntityMappingType().getEntityName(),
stateValue,
false,
toOne.isNullable()
);
}
applyLoadedState( entityDetails, statePosition, reference );
applyModelState( entityDetails, statePosition, reference );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Fix the data: UPDATE the offending rows so the FK is populated (find them with 'where <fk_column> is null' on the mapped table)
- Add/restore the NOT NULL constraint so violations cannot re-enter
- If nulls are legitimate, correct the mapping: @ManyToOne(optional=true) / @JoinColumn(nullable=true)
- During migration, exclude broken rows from the locking query until data is repaired
Example fix
// before @ManyToOne( optional = false ) @JoinColumn( name = "customer_id", nullable = false ) private Customer customer; // DB rows contain null customer_id // after (if nulls are legitimate) @ManyToOne( optional = true ) @JoinColumn( name = "customer_id" ) private Customer customer; -- or fix data: UPDATE Orders SET customer_id = :fallback WHERE customer_id IS NULL;
Defensive patterns
Strategy: validation
Validate before calling
-- verify mapping matches data before enabling non-optional to-ones SELECT count(*) FROM child_table WHERE fk_column IS NULL; -- must return 0 for @ManyToOne(optional=false) mappings
Prevention
- Run a null-check query on FK columns before tightening optional=false/nullable=false
- Keep NOT NULL constraints in the schema so bad rows cannot enter
- Enable schema validation (hibernate.hbm2ddl.auto=validate) to catch mapping/schema drift early
When it happens
Trigger: A row has NULL in the FK column of a to-one mapped as optional=false, read while applying results of a pessimistic/follow-on table lock (session.lock, lock-mode queries on collections or associations).
Common situations: Legacy or manually imported data violating NOT NULL; the DB constraint missing or dropped so nulls entered; the mapping tightened (optional=true to false) after null data already existed; hbm2ddl/validation disabled so schema and mapping drifted.
Related errors
- Entity `%s` with identifier value `%s` does not exist
- Entity '${persister.getEntityName()}' has no version and may
- Referenced entity '" + referencedEntityName + "' does not ex
- Referenced entity '" + referencedEntityName + "' has no prop
- 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/8ebe06503864feb0.
Report an issue: GitHub.