hibernate/hibernate-orm · error · StrategySelectionException

Implementation class [{}] does not implement strategy interf

Error message

Implementation class [{}] does not implement strategy interface [{}]

What it means

StrategySelectorBuilder.addExplicitStrategyRegistration() validates every explicit strategy registration (from a ServiceLoader-discovered StrategyRegistrationProvider or direct builder calls): the implementation class must be assignable to the strategy role. A mismatch throws StrategySelectionException naming both classes, because a registration that cannot stand in for its interface would break every later resolve against that strategy.

Source

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

	 */
	public <T> void addExplicitStrategyRegistration(Class<T> strategy, Class<? extends T> implementation, String name) {
		addExplicitStrategyRegistration( new SimpleStrategyRegistrationImpl<>( strategy, implementation, name ) );
	}

	/**
	 * Adds an explicit (as opposed to discovered) strategy registration.
	 *
	 * @param strategyRegistration The strategy implementation registration.
	 * @param <T> The type of the strategy.  Used to make sure that the strategy and implementation are type
	 * compatible.
	 */
	public <T> void addExplicitStrategyRegistration(StrategyRegistration<T> strategyRegistration) {
		final var strategyRole = strategyRegistration.getStrategyRole();
		if ( BOOT_LOGGER.isTraceEnabled() && !strategyRole.isInterface() ) {
			BOOT_LOGGER.registeringNonInterfaceStrategy( strategyRole.getName() );
		}
		if ( !strategyRole.isAssignableFrom( strategyRegistration.getStrategyImplementation() ) ) {
			throw new StrategySelectionException(
					"Implementation class [" + strategyRegistration.getStrategyImplementation().getName()
					+ "] does not implement strategy interface ["
					+ strategyRole.getName() + "]"
			);
		}
		explicitStrategyRegistrations.add( strategyRegistration );
	}

	/**
	 * Builds the selector.
	 *
	 * @param classLoaderService The class loading service used to (attempt to) resolve any un-registered
	 * strategy implementations.
	 *
	 * @return The selector.
	 */
	public StrategySelector buildSelector(ClassLoaderService classLoaderService) {
		final var strategySelector = new StrategySelectorImpl( classLoaderService );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Fix the registration so the implementation genuinely implements/extends the strategy interface (check the <T> generics of StrategyRegistration)
  2. Remove stale entries from the META-INF/services strategy registration provider file
  3. Add a unit test asserting strategyRole.isAssignableFrom(implementation) for every registration you ship

Example fix

// before
new StrategyRegistrationImpl<>(ConnectionProvider.class, // role
    MyCustomDialect.class, "myDialect");            // does not implement role

// after
new StrategyRegistrationImpl<>(Dialect.class,
    MyCustomDialect.class, "myDialect");
Defensive patterns

Strategy: validation

Validate before calling

// Validate a registration before contributing it
static <T> void check(Class<T> role, Class<? extends T> impl) {
    if (!role.isAssignableFrom(impl)) {
        throw new IllegalArgumentException(
            impl.getName() + " does not implement " + role.getName());
    }
}
check(Dialect.class, MyDialect.class);

Try / catch

try {
    builder.addExplicitStrategyRegistration(registration);
} catch (StrategySelectionException e) {
    // message names both classes; fix the pairing in the StrategyRegistrationProvider
    throw new ConfigurationException(e.getMessage(), e);
}

Prevention

When it happens

Trigger: A StrategyRegistrationProvider (registered via META-INF/services/org.hibernate.boot.registry.selector.StrategyRegistrationProvider) or explicit builder call that pairs a strategy interface with an implementation that does not implement/extend it - e.g., registering MyConnectionProvider under the Dialect role.

Common situations: Custom integration jars with copy-pasted or wrongly-generified StrategyRegistration classes; refactoring that dropped an implements/extends clause while the stale services file remained; mixed versions of an integration jar where the interface moved.

Related errors


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