hibernate/hibernate-orm · error · AnnotationException
@PropertyRef did not specify target attribute name: {}
Error message
@PropertyRef did not specify target attribute name: {} What it means
Hibernate's legacy '@org.hibernate.annotations.PropertyRef' annotation was placed on an association attribute, but its value() is empty or blank, so Hibernate has no target attribute name to resolve the foreign key against. The annotation exists precisely to name a non-PK target property, and a blank name is unusable.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java:120
if ( isNotBlank( annotationString ) ) {
buildJoinFormula( formula, parent );
}
else {
buildJoinColumn( column, mappedBy, parent, propertyHolder, inferredData );
}
}
handlePropertyRef( inferredData.getAttributeMember(), parent );
return parent;
}
private static void handlePropertyRef(MemberDetails attributeMember, AnnotatedJoinColumns parent) {
final var propertyRefUsage = attributeMember.getDirectAnnotationUsage( PropertyRef.class );
if ( propertyRefUsage != null ) {
final String referencedPropertyName = propertyRefUsage.value();
if ( isBlank( referencedPropertyName ) ) {
throw new AnnotationException(
"@PropertyRef did not specify target attribute name: " + attributeMember );
}
parent.referencedProperty = referencedPropertyName;
}
}
static AnnotatedJoinColumns buildJoinColumnsWithFormula(
JoinFormula joinFormula,
Map<String, Join> secondaryTables,
PropertyHolder propertyHolder,
PropertyData inferredData,
MetadataBuildingContext context) {
final var joinColumns = new AnnotatedJoinColumns();
joinColumns.setBuildingContext( context );
joinColumns.setJoins( secondaryTables );
joinColumns.setPropertyHolder( propertyHolder );
joinColumns.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) );
buildJoinFormula( joinFormula, joinColumns );View on GitHub (pinned to fad1729dce)
Solutions
- Set the annotation value to the exact name of the target attribute: '@PropertyRef("userId")'.
- Prefer the JPA-standard equivalent: a unique @ManyToOne on the target plus 'referencedColumnName' on @JoinColumn, which is validated and better supported.
- Add a compile-time or test-scan check that every @PropertyRef value is non-blank.
Example fix
// before
@ManyToOne(fetch = FetchType.LAZY)
@PropertyRef("") // blank target
private User supervisor;
// after
@ManyToOne(fetch = FetchType.LAZY)
@PropertyRef("userName")
private User supervisor; Defensive patterns
Strategy: validation
Validate before calling
// Guard: every @PropertyRef must name a target attribute
for (Field f : cls.getDeclaredFields()) {
PropertyRef ref = f.getAnnotation(PropertyRef.class);
if (ref != null && ref.value().isBlank()) {
throw new IllegalStateException("Blank @PropertyRef on " + cls.getName() + "." + f.getName());
}
} Try / catch
try {
factory = cfg.buildSessionFactory();
} catch (AnnotationException e) {
if (e.getMessage().startsWith("@PropertyRef did not specify")) {
// fill in the target attribute name on the field printed in the message
}
throw e;
} Prevention
- Prefer JPA-standard references (unique @ManyToOne + referencedColumnName) over @PropertyRef.
- Grep the codebase for '@PropertyRef("")' as part of pre-commit checks.
- Whenever renaming a referenced property, search for its name in all @PropertyRef values.
When it happens
Trigger: '@PropertyRef("")' or '@PropertyRef(" ")' on a @ManyToOne/@OneToOne field; a PropertyRef constant that resolves to an empty string at compile time; refactoring renamed the referenced property and the string was blanked out.
Common situations: Hand-written string values that were never filled in; migrating old hbm.xml <many-to-one property-ref="..."> entries to annotations and losing the value; refactoring tools stripping the constant.
Related errors
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
- Collection '<propertyName>' was annotated '@Collate'
- Root entity '<entityName>' is annotated '@DiscriminatorOptio
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/136757ed03c375f6.
Report an issue: GitHub.