hibernate/hibernate-orm · error · EnhancementException
Enhancement of [%s] failed because no underlying field named
Error message
Enhancement of [%s] failed because no underlying field named [%s] exists for property accessor method [%s] (ensure all property accessor methods have a matching field)
What it means
During enhancement Hibernate treats JavaBeans-style accessors (get/set/is methods) as property accessors and expects a backing field of the derived name. When no such field exists, behavior depends on the UnsupportedEnhancementStrategy: SKIP logs propertyAccessorNoFieldSkip and moves on, but FAIL (the case here) throws EnhancementException telling you which class/accessor lacked the field - the method looks like an accessor but there is nothing to instrument.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java:716
return false;
}
@SuppressWarnings("deprecation")
private static boolean handleMissingField(
TypeDescription managedCtClass,
UnsupportedEnhancementStrategy strategy,
MethodDescription methodDescription,
String fieldName) {
return switch ( strategy ) {
case SKIP -> {
ENHANCEMENT_LOGGER.propertyAccessorNoFieldSkip(
managedCtClass.getName(),
fieldName,
methodDescription.getName()
);
yield true;
}
case FAIL -> throw new EnhancementException( String.format(
"Enhancement of [%s] failed because no underlying field named [%s] exists for property accessor method [%s]"
+ " (ensure all property accessor methods have a matching field)",
managedCtClass.getName(),
fieldName,
methodDescription.getName()
) );
case LEGACY -> throw new AssertionFailure( "Unexpected strategy at this point: " + strategy );
};
}
private static @Nullable String propertyName(MethodDescription methodDescription) {
return getJavaBeansFieldName( trimGetterName( methodDescription.getActualName() ) );
}
private static @Nonnull String trimGetterName(String methodName) {
if ( methodName.startsWith( "get" ) || methodName.startsWith( "set" ) ) {
return methodName.substring( 3 );
}View on GitHub (pinned to fad1729dce)
Solutions
- Rename the method so it no longer matches the JavaBeans accessor pattern (e.g. computeTotal(), nameOf()) - Hibernate then ignores it during enhancement.
- Add the matching field the accessor exposes, so instrumentation has something to attach to.
- Configure the unsupported-enhancement strategy to SKIP so these methods are logged (propertyAccessorNoFieldSkip) and enhancement continues instead of failing.
- Audit with the message's triple (class, fieldName, methodName): propertyName() derives the field name from the method name, so the mismatch is usually visible immediately.
Example fix
// before
public class Invoice {
public BigDecimal getTotal() { return lines.stream().map(Line::getAmt).reduce(ZERO, ADD); }
// no field 'total' -> EnhancementException with strategy FAIL
}
// after
public class Invoice {
public BigDecimal computeTotal() { return lines.stream().map(Line::getAmt).reduce(ZERO, ADD); }
} Defensive patterns
Strategy: fallback
Validate before calling
// before enhancement, flag accessor-named methods without backing fields
for ( var m : entityClass.getDeclaredMethods() ) {
java.util.Optional<String> field = javaBeansFieldOf( m.getName() ); // getFoo/isFoo/setFoo -> foo
if ( field.isPresent() && java.util.Arrays.stream( entityClass.getDeclaredFields() )
.noneMatch( f -> f.getName().equals( field.get() ) ) ) {
issues.add( entityClass.getName() + "#" + m.getName() + " has no field " + field.get() );
}
} Prevention
- Avoid JavaBeans accessor names (get*/set*/is*) for computed or delegated methods on enhanced classes.
- Keep field names and accessor names exactly aligned in code review and refactors.
- Configure the unsupported-enhancement strategy to SKIP for classes where accessor-like helpers are intentional.
When it happens
Trigger: An entity (or extended-enhancement target) has a method named like a getter/setter (getTotal(), isValid(), setName(...)) with no corresponding field 'total'/'valid'/'name' - computed or delegated properties - while the enhancement strategy is FAIL.
Common situations: DTO-like entities with calculated getters; lombok @Getter on a parent interface; methods delegating to a wrapped object; renaming a field without renaming its accessor (or vice versa) during a refactor; boolean 'isXxx' naming where the field is 'xxxFix' style.
Related errors
- Couldn't find column [${structColumnName}] that was defined
- Failed to enhance class {className}
- Failed to discover types for class {className}
- Mismatch between Hibernate version used for bytecode enhance
- Support for %s was enabled during enhancement, but `%s` was
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/218f6ea93efaca35.
Report an issue: GitHub.