hibernate/hibernate-orm · error · PersistenceException

Enhancement requires a temp class loader, but none was given

Error message

Enhancement requires a temp class loader, but none was given [persistence unit: {}] 

What it means

The EntityManagerFactoryBuilderImpl path for runtime enhancement: after a ClassTransformer is pushed to the environment (EE container callback), Hibernate asks PersistenceUnitInfo.getTempClassLoader() for a classloader to discover types to transform. If that method returns null while enhancement features are enabled, bootstrap fails with this PersistenceException (the unit name is appended via exceptionHeader()).

Source

Thrown at hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java:438

		if ( !lazyInitializationEnabled ) {
			DEPRECATION_LOGGER.deprecatedSettingForRemoval( ENHANCER_ENABLE_LAZY_INITIALIZATION, "true" );
		}
		if ( !dirtyTrackingEnabled ) {
			DEPRECATION_LOGGER.deprecatedSettingForRemoval( ENHANCER_ENABLE_DIRTY_TRACKING, "true" );
		}

		if ( dirtyTrackingEnabled || lazyInitializationEnabled || associationManagementEnabled ) {
			final var enhancementContext =
					getEnhancementContext( dirtyTrackingEnabled,
							lazyInitializationEnabled,
							associationManagementEnabled );
			// push back class transformation to the environment; for the time being this only has any effect in EE
			// container situations, calling back into PersistenceUnitInfo#addClassTransformer
			final var classTransformer = persistenceUnit.pushClassTransformer( enhancementContext );
			if ( classTransformer != null ) {
				final var classLoader = persistenceUnit.getTempClassLoader();
				if ( classLoader == null ) {
					throw new PersistenceException( "Enhancement requires a temp class loader, but none was given"
							+ exceptionHeader() );
				}
				discoverTypesToTransform( metadataSources, classTransformer, classLoader );
			}
		}
	}

	private static void discoverTypesToTransform(
			MetadataSources metadataSources, ClassTransformer classTransformer, ClassLoader classLoader) {
		for ( var binding : metadataSources.getHbmXmlBindings() ) {
			final var hibernateMapping = binding.getRoot();
			final String packageName = hibernateMapping.getPackage();
			for ( var clazz : hibernateMapping.getClazz() ) {
				final String className =
						packageName == null || packageName.isEmpty()
								? clazz.getName()
								: packageName + '.' + clazz.getName();
				try {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Move enhancement to build time (Hibernate Gradle/Maven plugin) and set the three hibernate.enhancer.enable* settings to false
  2. Or implement getTempClassLoader() in your PersistenceUnitInfo to return a dedicated throwaway ClassLoader
  3. Verify the container actually supports runtime class transformation before enabling enhancer settings

Example fix

// before: runtime enhancement enabled, getTempClassLoader() returns null -> PersistenceException

// after (option A: implement the SPI)
class MyPersistenceUnitInfo implements PersistenceUnitInfo {
    @Override public ClassLoader getTempClassLoader() {
        return new URLClassLoader(classpathUrls, getClass().getClassLoader()); // never null
    }
}
// after (option B): build-time enhancement + disable runtime flags
// props.put("hibernate.enhancer.enableDirtyTracking", "false"); ...
Defensive patterns

Strategy: validation

Validate before calling

// Either opt out of runtime enhancement (preferred in SE/servlet containers)
props.put("hibernate.enhancer.enableDirtyTracking", "false");
props.put("hibernate.enhancer.enableLazyInitialization", "false");
props.put("hibernate.enhancer.enableAssociationManagement", "false");
// or, in your PersistenceUnitInfo, never return null:
// @Override public ClassLoader getTempClassLoader() {
//     return new URLClassLoader(classpathUrls, getClass().getClassLoader());
// }

Prevention

When it happens

Trigger: Runtime enhancement active (hibernate.enhancer.enableDirtyTracking / enableLazyInitialization / enableAssociationManagement not all false) in a container whose PersistenceUnitInfo returns null from getTempClassLoader(), after a class transformer was successfully registered.

Common situations: Servlet containers or lightweight SE runtimes that implement PersistenceUnitInfo partially (getTempClassLoader returns null by design in several implementations); custom test harnesses enabling enhancement at runtime.

Related errors


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