hibernate/hibernate-orm · error · HibernateException
Unable to load class {}
Error message
Unable to load class {} What it means
GroupsPerOperation parses the per-operation validation group settings (jakarta.persistence.validation.group.pre-persist|pre-update|pre-remove, comma-separated class names) and loads each name through Hibernate's ClassLoaderService. A ClassLoadingException for any single group name is rethrown as 'Unable to load class <name>', aborting SessionFactory construction.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/beanvalidation/GroupsPerOperation.java:89
if ( property instanceof Class<?>[] classes ) {
return classes;
}
if ( property instanceof String string ) {
final String[] groupNames = split( ",", string );
if ( groupNames.length == 1 && groupNames[0].isEmpty() ) {
return EMPTY_GROUPS;
}
final List<Class<?>> groupsList = new ArrayList<>( groupNames.length );
for ( String groupName : groupNames ) {
final String cleanedGroupName = groupName.trim();
if ( !cleanedGroupName.isEmpty() ) {
try {
groupsList.add( classLoaderAccess.classForName( cleanedGroupName ) );
}
catch ( ClassLoadingException e ) {
throw new HibernateException( "Unable to load class " + cleanedGroupName, e );
}
}
}
return groupsList.toArray( new Class<?>[0] );
}
//null is bad and excluded by instanceof => exception is raised
throw new HibernateException( JAKARTA_JPA_GROUP_PREFIX
+ operation.getJakartaGroupPropertyName()
+ " is of unknown type: String or Class<?>[] only");
}
public Class<?>[] get(Operation operation) {
return groupsPerOperation.get( operation );
}
public enum Operation {
PERSIST( "persist", JPA_GROUP_PREFIX + "pre-persist", JAKARTA_JPA_GROUP_PREFIX + "pre-persist" ),View on GitHub (pinned to fad1729dce)
Solutions
- Fix typos and use the fully-qualified binary name (dots, no .class suffix, no slashes)
- Ensure the jar containing the group class is deployed with the app and visible to Hibernate's classloader
- After refactors, grep configuration files for stale group FQCNs
Example fix
// before
props.put("jakarta.persistence.validation.group.pre-persist", "com.acme.MyCheck"); // typo / class not deployed
// after
props.put("jakarta.persistence.validation.group.pre-persist", "com.acme.validation.OnPersist");
// and ensure com.acme.validation.OnPersist ships in the deployed jar Defensive patterns
Strategy: validation
Validate before calling
// resolve every configured group class before building the factory
for (String key : List.of("jakarta.persistence.validation.group.pre-persist",
"jakarta.persistence.validation.group.pre-update",
"jakarta.persistence.validation.group.pre-remove")) {
Object v = settings.get(key);
if (v instanceof String s)
for (String name : s.split(",")) {
String cn = name.trim();
if (!cn.isEmpty())
Class.forName(cn); // throws early with a clear message if mistyped/not deployed
}
} Try / catch
try {
emf = Persistence.createEntityManagerFactory("pu", settings);
} catch (HibernateException e) {
if (e.getMessage().startsWith("Unable to load class") && e.getMessage().contains("validation"))
throw new IllegalStateException("Validation group class missing: " + e.getMessage(), e);
throw e;
} Prevention
- Keep group class names in constants shared with config to avoid drift
- After renaming/moving group classes, update all persistence unit properties
When it happens
Trigger: Setting e.g. jakarta.persistence.validation.group.pre-persist=com.acme.MyChecks where MyChecks is misspelled, not compiled into the deployed artifact, or invisible to Hibernate's aggregation classloader.
Common situations: The group class lives in another module/jar that is not deployed; refactoring renamed or moved the group class; WAR/EAR classloader visibility rules in application servers hiding the class from Hibernate.
Related errors
- jakarta.persistence.validation.group.{} is of unknown type:
- Unable to load TypeSafeActivator class
- Can't load class: {}
- The {storageEngine} storage engine is not supported
- Audit graph mutation plan used with non-graph action queue
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/41be5070e59d2887.
Report an issue: GitHub.