{"record":{"id":"5b60d96fb9073921","repo":"junit-team/junit5","slug":"the-following-testinstancefactory-extensions-were","errorCode":null,"errorMessage":"The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s","messagePattern":"The following TestInstanceFactory extensions were registered for test class \\[(.+?)\\], but only one is permitted: (.+?)","errorType":"exception","errorClass":"ExtensionConfigurationException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java","lineNumber":311,"sourceCode":"\t\tthis.testInstanceFactory = null;\n\t}\n\n\tprivate @Nullable TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) {\n\t\tList<TestInstanceFactory> factories = registry.getExtensions(TestInstanceFactory.class);\n\n\t\tif (factories.size() == 1) {\n\t\t\treturn factories.get(0);\n\t\t}\n\n\t\tif (factories.size() > 1) {\n\t\t\tString factoryNames = factories.stream()//\n\t\t\t\t\t.map(factory -> factory.getClass().getName())//\n\t\t\t\t\t.collect(joining(\", \"));\n\n\t\t\tString errorMessage = \"The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s\".formatted(\n\t\t\t\tgetTestClass().getName(), factoryNames);\n\n\t\t\tthrow new ExtensionConfigurationException(errorMessage);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate TestInstancesProvider testInstancesProvider(JupiterEngineExecutionContext parentExecutionContext,\n\t\t\tClassExtensionContext ourExtensionContext) {\n\n\t\t// For Lifecycle.PER_CLASS, ourExtensionContext.getTestInstances() is used to store the instance.\n\t\t// Otherwise, extensionContext.getTestInstances() is always empty and we always create a new instance.\n\t\treturn (registry, context) -> ourExtensionContext.getTestInstances().orElseGet(\n\t\t\t() -> instantiateAndPostProcessTestInstance(parentExecutionContext, ourExtensionContext, registry,\n\t\t\t\tcontext));\n\t}\n\n\tprivate TestInstances instantiateAndPostProcessTestInstance(JupiterEngineExecutionContext parentExecutionContext,\n\t\t\tClassExtensionContext ourExtensionContext, ExtensionRegistry registry,\n\t\t\tJupiterEngineExecutionContext context) {","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java#L293-L329","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@ExtendWith({MockitoExtension.class, MyKotlinFactory.class})\nclass MyTest { }\n// after - whitelist only one factory globally in junit-platform.properties\njunit.jupiter.execution.extensions.enabled.extension.types=org.junit.jupiter.api.extension.TestInstanceFactory,com.example.MyKotlinFactory","handlingStrategy":"validation","validationCode":"long factoryCount = Stream.of(MyTest.class.getAnnotations())\n    .filter(a -> a instanceof ExtendWith)\n    .map(a -> ((ExtendWith) a).value())\n    .flatMap(Arrays::stream)\n    .filter(c -> TestInstanceFactory.class.isAssignableFrom(c))\n    .count();\n// also scan @RegisterExtension fields/params and ServiceLoader entries\nif (factoryCount > 1) throw new IllegalStateException(\"Multiple TestInstanceFactory registered\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["extension","test-instance-factory","configuration","multiple-registrations"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}