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

  1. 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.
  2. Check the exact type name in the message against orm.xml/hbm.xml, @Type values and TypeContributor registrations for typos or wrong packages.
  3. 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.
  4. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/6b3c7dafd9253757. Report an issue: GitHub.