hibernate/hibernate-orm · error · EnhancementException
Failed to discover types for class {className}
Error message
Failed to discover types for class {className} What it means
Before enhancing, the enhancer runs a discovery pass: EnhancerImpl.discoverTypes() registers the class bytes in the type pool, resolves the TypeDescription, then calls enhancementContext.discoverCompositeTypes(...) to walk embeddable/composite types. Any RuntimeException in that pass (typically unresolved types when describing the class or its referenced components) is wrapped as EnhancementException('Failed to discover types for class <name>').
Source
Thrown at hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java:181
throw new EnhancementException( "Failed to enhance class " + className, e );
}
finally {
typePool.deregisterClassNameAndBytes( safeClassName );
}
}
@Override
public void discoverTypes(String className, byte[] originalBytes) {
if ( originalBytes != null ) {
typePool.registerClassNameAndBytes( className, originalBytes );
}
try {
final var typeDescription = typePool.describe( className ).resolve();
enhancementContext.registerDiscoveredType( typeDescription, Type.PersistenceType.ENTITY );
enhancementContext.discoverCompositeTypes( typeDescription, typePool );
}
catch (RuntimeException e) {
throw new EnhancementException( "Failed to discover types for class " + className, e );
}
finally {
typePool.deregisterClassNameAndBytes( className );
}
}
private DynamicType.Builder<?> doEnhance(
Supplier<DynamicType.Builder<?>> builderSupplier,
TypeDescription managedCtClass) {
if ( alreadyEnhanced( managedCtClass ) ) {
// The class already implements `Managed`.
// There are 2 broad cases:
// 1. the user manually implemented `Managed`
// 2. the class was previously enhanced
// In either case, look for `@EnhancementInfo` and,
// if found, verify we can "re-enhance" the class
final var infoAnnotation =
managedCtClass.getDeclaredAnnotations()View on GitHub (pinned to fad1729dce)
Solutions
- Read the cause chain to get the unresolved type name, then add the artifact containing it to the enhancement plugin's classpath.
- Give the enhancement task the same classpath as compilation plus runtime dependencies (in Gradle: classpath = sourceSets.main.runtimeClasspath).
- Run a clean build to rule out stale incremental class files feeding the type pool.
- Upgrade hibernate-core if the failure is internal to discovery rather than a missing type.
Example fix
// before (gradle)
hibernateEnhance { classes { sourceSets.main.output } } // no classpath -> discovery fails
// after
hibernateEnhance {
classes { sourceSets.main.output }
classpath { sourceSets.main.runtimeClasspath } // embeddables/refs resolvable
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: every type referenced by the entity must resolve on the enhancement classpath
static boolean discoverable(ClassLoader enhancerCl, String... typeNames) {
for ( String n : typeNames ) {
try { Class.forName( n, false, enhancerCl ); }
catch ( ClassNotFoundException e ) { return false; }
}
return true;
} Try / catch
try { enhancer.discoverTypes( className, bytes ); }
catch ( EnhancementException e ) {
if ( e.getMessage() != null && e.getMessage().startsWith( "Failed to discover types for class" ) ) {
// cause names the unresolved type -> fix plugin classpath, not the entity code
buildLog.error( "enhancement classpath incomplete: {}", String.valueOf( e.getCause() ) );
}
throw e;
} Prevention
- Configure the enhancement plugin with the full runtimeClasspath, not just compiled output.
- Run enhancement after all contributing modules are compiled.
- Treat 'Failed to discover types' as a classpath problem first - the entity source is rarely at fault.
When it happens
Trigger: discoverTypes(className, originalBytes) where typePool.describe(className).resolve() cannot resolve the class from registered bytes, or discoverCompositeTypes hits an embeddable/superinterface that is not on the enhancement classpath (resolve() throws on unresolved descriptions).
Common situations: Gradle/Maven enhancement plugin configured without the project's runtime dependencies, so entities referencing other modules or jars fail type discovery; partial incremental builds where a dependent class's bytes are stale; fat-jar/shaded layouts hiding referenced types from the enhancer's loader.
Related errors
- Unable to perform extended enhancement - Unable to locate [%
- Error calling Value#setTypeUsingReflection: containingClassN
- Failed to enhance 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/785a8d7ef55644bb.
Report an issue: GitHub.