hibernate/hibernate-orm · error · StrategySelectionException

Registered strategy [%s] is not a subtype of [%s]

Error message

Registered strategy [%s] is not a subtype of [%s]

What it means

While collecting a strategy's registered implementors, each entry in the name-to-implementor map is re-checked for assignability; a stored class that is not a subtype of the strategy throws StrategySelectionException naming both classes. Registrations are validated when added, so surviving to this check indicates corrupted registration state: the same class loaded by two different classloaders, or entries inserted under a wrong key via the deprecated registerStrategyImplementor.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/registry/selector/internal/StrategySelectorImpl.java:140

				creator
		);
	}

	@Override
	public <T> Collection<Class<? extends T>> getRegisteredStrategyImplementors(Class<T> strategy) {
		final var lazyServiceResolver = lazyStrategyImplementorByStrategyMap.get( strategy );
		if ( lazyServiceResolver != null ) {
			throw new StrategySelectionException( "Can't use this method on for strategy types which are embedded in the core library" );
		}
		final var registrations = namedStrategyImplementorByStrategyMap.get( strategy );
		if ( registrations == null ) {
			return emptySet();
		}
		else {
			final Set<Class<? extends T>> implementors = new HashSet<>();
			for ( var registration : registrations.values() ) {
				if ( !strategy.isAssignableFrom( registration ) ) {
					throw new StrategySelectionException(
							String.format(
									"Registered strategy [%s] is not a subtype of [%s]",
									registration.getName(),
									strategy.getName()
							)
					);
				}
				implementors.add( registration.asSubclass( strategy ) );
			}
			return implementors;
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T resolveStrategy(
			Class<T> strategy,
			Object strategyReference,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Deduplicate hibernate-core on the classpath (mvn dependency:tree / gradle dependencies; check server modules vs deployment)
  2. Stop using deprecated registerStrategyImplementor with unchecked types; re-register through a typed StrategyRegistration
  3. Restart with a single, consistent Hibernate version across all modules
Defensive patterns

Strategy: try-catch

Validate before calling

// Consistency check at startup: one classloader, one Hibernate version
Class<?> h1 = Class.forName("org.hibernate.Version", false, getClass().getClassLoader());
if (h1.getProtectionDomain().getCodeSource() == null) {
    log.warn("Hibernate loaded from unknown source - check for shaded jars");
}

Try / catch

try {
    return strategySelector.getRegisteredStrategyImplementors(strategy);
} catch (StrategySelectionException e) {
    if (e.getMessage().contains("is not a subtype of")) {
        // registration map corrupted by duplicate jars/classloaders - audit the classpath
        log.error("Duplicate Hibernate artifacts detected; run dependency:tree", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getRegisteredStrategyImplementors on a registry whose registration map holds mismatched entries - typically duplicated Hibernate jars across parent/child classloaders in an app server, or unchecked use of the deprecated registerStrategyImplementor with a non-subtype class.

Common situations: Deploying hibernate-core both in the server's lib directory and inside the WAR; shaded/fat jars embedding Hibernate classes alongside the real dependency; mixed Hibernate versions on one classpath.

Related errors


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