hibernate/hibernate-orm · error · UnsupportedOperationException
Unloadable Java type: " + typeName
Error message
Unloadable Java type: " + typeName
What it means
UnknownBasicJavaType is registered by the JavaTypeRegistry when a basic type is known only by name and its Class cannot be loaded by the active classloader. The descriptor carries just the type name, so getJavaType() throws UnsupportedOperationException('Unloadable Java type: <name>') as soon as real class access is needed (binding, reflection, DDL generation). The root cause is a classpath/classloader problem, not mapping semantics.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/UnknownBasicJavaType.java:50
super( type, mutabilityPlan );
this.typeName = type.getTypeName();
}
public UnknownBasicJavaType(Type type, MutabilityPlan<T> mutabilityPlan) {
super( type, mutabilityPlan );
this.typeName = type.getTypeName();
}
@Override
public String getTypeName() {
return typeName;
}
@Override
public Type getJavaType() {
final Type type = super.getJavaType();
if ( type == null ) {
throw new UnsupportedOperationException( "Unloadable Java type: " + typeName );
}
else {
return type;
}
}
@Override
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {
throw new JdbcTypeRecommendationException(
"Could not determine recommended JdbcType for Java type '" + getTypeName() + "'"
);
}
@Override
public <X> X unwrap(T value, Class<X> type, WrapperOptions options) {
if ( type.isAssignableFrom( getJavaTypeClass() ) ) {
return type.cast( value );
}View on GitHub (pinned to fad1729dce)
Solutions
- Make the named class loadable by the SessionFactory's classloader: put the domain jar on the tool/plugin classpath or align the TCCL with the loader that owns the entities.
- Check the exact type name in the message against orm.xml/hbm.xml, @Type values and TypeContributor registrations for typos or wrong packages.
- For schema tooling, run it in the same JVM/module path as the application (SchemaExport via the persistence unit) instead of a separate bare classpath.
- Build the StandardServiceRegistry with the owning classloader (new StandardServiceRegistryBuilder(entityClassLoader)) so Hibernate uses it for name resolution.
Example fix
// before (tool runs with its own classloader; entity class invisible)
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().build();
Metadata metadata = new MetadataSources(registry).addResource("org/acme/Order.orm.xml").buildMetadata();
// -> Unloadable Java type: org.acme.Order when metadata touches the class
// after: build the registry with the application classloader
StandardServiceRegistry registry = new StandardServiceRegistryBuilder(MyApp.class.getClassLoader())
.build(); Defensive patterns
Strategy: validation
Validate before calling
// Fail fast at startup: every mapping-referenced class must load
static void assertAllLoadable(ClassLoader cl, String... classNames) {
for (String name : classNames) {
try {
Class.forName(name, false, cl);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Type not on classpath: " + name, e);
}
}
} Try / catch
try {
sessionFactory = metadata.buildSessionFactory();
} catch (UnsupportedOperationException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unloadable Java type")) {
// message names the missing class: add it to the classpath of the SessionFactory's classloader
} else {
throw e;
}
} Prevention
- Run schema tooling in the same JVM/classpath as the domain model
- Pass the owning classloader when building the StandardServiceRegistry
- Class.forName every mapping-referenced class during a startup smoke test
When it happens
Trigger: SessionFactory bootstrap resolves a type by class name that the classloader cannot load; later anything calls getJavaType()/getJavaTypeClass() on that descriptor - metamodel building, schema export/validation, or binding a value at flush time.
Common situations: Schema generation run from Ant/Gradle/Maven plugins without the entity classes on the plugin classpath; app servers, OSGi or native-image where the Thread-Context ClassLoader differs from the entities' loader; a typo in a class name in orm.xml/hbm.xml or a TypeContributor; hot-reload tooling dropping classes.
Related errors
- Unable to locate schema [{}] via classpath
- Multiple BeanContainer service implementations found (set 'h
- A bean manager was provided via 'jakarta.persistence.bean.ma
- Multiple SchemaManagementTool service registrations found vi
- Could not determine recommended JdbcType for Java type '" +
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/6b3c7dafd9253757.
Report an issue: GitHub.