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
- Fix the registration so the implementation genuinely implements/extends the strategy interface (check the <T> generics of StrategyRegistration)
- Remove stale entries from the META-INF/services strategy registration provider file
- 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
- Unit-test every shipped StrategyRegistration for role.isAssignableFrom(implementation)
- Keep META-INF/services entries in sync when interfaces change during refactors
- Avoid raw types on StrategyRegistration - let generics catch mismatches at compile time
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
- Detected a second LazyServiceResolver replacing an existing
- Multiple active MetadataBuilder definitions were discovered
- Default resolver threw exception
- Multiple MutationExecutorService service registrations found
- Unable to determine JAR Url from <url>. Cause: <cause>
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f43ffa5d3803ea2b.
Report an issue: GitHub.