junit-team/junit5 · error · ExtensionConfigurationException
The following TestInstanceFactory extensions were…
Error message
The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s
What it means
Thrown as ExtensionConfigurationException when more than one TestInstanceFactory extension is registered for a single test class. JUnit Jupiter only allows one factory to create the test instance, so the framework refuses to pick arbitrarily and aborts class execution.
Solutions
- Inspect the factory names listed in the message to identify the two conflicting factories.
- Disable one via the junit.jupiter.execution.extensions.enabled.extension-types filter property (or the deprecated junit.jupiter.extensions.disabled.autodetection) so only the intended factory is active.
- Remove the duplicate @ExtendWith / @RegisterEntry / ServiceLoader registration from your test or classpath.
- If both are legitimate for different tests, scope them to disjoint classes via @ExtendWith on each rather than globally.
Example fix
// before
@ExtendWith({MockitoExtension.class, MyKotlinFactory.class})
class MyTest { }
// after - whitelist only one factory globally in junit-platform.properties
junit.jupiter.execution.extensions.enabled.extension.types=org.junit.jupiter.api.extension.TestInstanceFactory,com.example.MyKotlinFactory Defensive patterns
Strategy: validation
Validate before calling
long factoryCount = Stream.of(MyTest.class.getAnnotations())
.filter(a -> a instanceof ExtendWith)
.map(a -> ((ExtendWith) a).value())
.flatMap(Arrays::stream)
.filter(c -> TestInstanceFactory.class.isAssignableFrom(c))
.count();
// also scan @RegisterExtension fields/params and ServiceLoader entries
if (factoryCount > 1) throw new IllegalStateException("Multiple TestInstanceFactory registered"); Prevention
- Audit META-INF/services for duplicate TestInstanceFactory registrations from different libraries.
- Scope @ExtendWith with TestInstanceFactory to specific test classes only, never globally.
- Use junit.jupiter.execution.extensions.enabled.extension.types to whitelist exactly one factory.
When it happens
Trigger: Registering multiple TestInstanceFactory implementations on the same test class - via @RegisterExtension fields/parameters, @ExtendWith meta-annotations, META-INF/services auto-registration, or JupiterConfiguration service-loader entries. The throw site is in ClassBasedTestDescriptor.resolveTestInstanceFactory when factories.size() > 1.
Common situations: Two test libraries both ship a TestInstanceFactory (e.g. a Mockito/Kotest/Testcontainers factory) and both get auto-registered via ServiceLoader; a developer adds @ExtendWith(CustomFactory.class) while a base class already registers another; mixing @RegisterExtension fields of factory type.
Related errors
- TestInstanceFactory [ ] failed to instantiate test class [ ]
- Can only resolve @TempDir
- Cannot override the standard style 'NONE'
- Chain of InvocationInterceptors called invocation multiple…
- Chain of InvocationInterceptors never called invocation
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/5b60d96fb9073921.
Report an issue: GitHub.
Appendix: source
Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java:311
this.testInstanceFactory = null;
}
private @Nullable TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) {
List<TestInstanceFactory> factories = registry.getExtensions(TestInstanceFactory.class);
if (factories.size() == 1) {
return factories.get(0);
}
if (factories.size() > 1) {
String factoryNames = factories.stream()//
.map(factory -> factory.getClass().getName())//
.collect(joining(", "));
String errorMessage = "The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s".formatted(
getTestClass().getName(), factoryNames);
throw new ExtensionConfigurationException(errorMessage);
}
return null;
}
private TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext,
ClassExtensionContext ourExtensionContext) {
// For Lifecycle.PER_CLASS, ourExtensionContext.getTestInstances() is used to store the instance.
// Otherwise, extensionContext.getTestInstances() is always empty and we always create a new instance.
return (registry, context) -> ourExtensionContext.getTestInstances().orElseGet(
() -> instantiateAndPostProcessTestInstance(parentExecutionContext, ourExtensionContext, registry,
context));
}
private TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext,
ClassExtensionContext ourExtensionContext, ExtensionRegistry registry,
JupiterEngineExecutionContext context) {View on GitHub (pinned to f070c699a0)