{"record":{"id":"136757ed03c375f6","repo":"hibernate/hibernate-orm","slug":"propertyref-did-not-specify-target-attribute-name","errorCode":null,"errorMessage":"@PropertyRef did not specify target attribute name: {}","messagePattern":"@PropertyRef did not specify target attribute name: (.+?)","errorType":"exception","errorClass":"AnnotationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java","lineNumber":120,"sourceCode":"\t\t\tif ( isNotBlank( annotationString ) ) {\n\t\t\t\tbuildJoinFormula( formula, parent );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbuildJoinColumn( column, mappedBy, parent, propertyHolder, inferredData );\n\t\t\t}\n\t\t}\n\n\t\thandlePropertyRef( inferredData.getAttributeMember(), parent );\n\n\t\treturn parent;\n\t}\n\n\tprivate static void handlePropertyRef(MemberDetails attributeMember, AnnotatedJoinColumns parent) {\n\t\tfinal var propertyRefUsage = attributeMember.getDirectAnnotationUsage( PropertyRef.class );\n\t\tif ( propertyRefUsage != null ) {\n\t\t\tfinal String referencedPropertyName = propertyRefUsage.value();\n\t\t\tif ( isBlank( referencedPropertyName ) ) {\n\t\t\t\tthrow new AnnotationException(\n\t\t\t\t\t\t\"@PropertyRef did not specify target attribute name: \" + attributeMember );\n\t\t\t}\n\t\t\tparent.referencedProperty = referencedPropertyName;\n\t\t}\n\t}\n\n\tstatic AnnotatedJoinColumns buildJoinColumnsWithFormula(\n\t\t\tJoinFormula joinFormula,\n\t\t\tMap<String, Join> secondaryTables,\n\t\t\tPropertyHolder propertyHolder,\n\t\t\tPropertyData inferredData,\n\t\t\tMetadataBuildingContext context) {\n\t\tfinal var joinColumns = new AnnotatedJoinColumns();\n\t\tjoinColumns.setBuildingContext( context );\n\t\tjoinColumns.setJoins( secondaryTables );\n\t\tjoinColumns.setPropertyHolder( propertyHolder );\n\t\tjoinColumns.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) );\n\t\tbuildJoinFormula( joinFormula, joinColumns );","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumns.java#L102-L138","documentation":"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.","triggerScenarios":"'@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.","commonSituations":"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.","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."],"exampleFix":"// before\n@ManyToOne(fetch = FetchType.LAZY)\n@PropertyRef(\"\") // blank target\nprivate User supervisor;\n\n// after\n@ManyToOne(fetch = FetchType.LAZY)\n@PropertyRef(\"userName\")\nprivate User supervisor;","handlingStrategy":"validation","validationCode":"// Guard: every @PropertyRef must name a target attribute\nfor (Field f : cls.getDeclaredFields()) {\n    PropertyRef ref = f.getAnnotation(PropertyRef.class);\n    if (ref != null && ref.value().isBlank()) {\n        throw new IllegalStateException(\"Blank @PropertyRef on \" + cls.getName() + \".\" + f.getName());\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    factory = cfg.buildSessionFactory();\n} catch (AnnotationException e) {\n    if (e.getMessage().startsWith(\"@PropertyRef did not specify\")) {\n        // fill in the target attribute name on the field printed in the message\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["hibernate","property-ref","legacy-annotation","orm-mapping"],"backgroundTag":"property-ref-misconfiguration","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}