{"record":{"id":"e129b7d9771f95bc","repo":"junit-team/junit5","slug":"discovered-multiple-competing-parameterresolvers-f","errorCode":null,"errorMessage":"Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s","messagePattern":"Discovered multiple competing ParameterResolvers for parameter \\[(.+?)\\] in (.+?) \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"ParameterResolutionException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java","lineNumber":145,"sourceCode":"\t\t\t// @formatter:off\n\t\t\tList<ParameterResolver> matchingResolvers = extensionRegistry.stream(ParameterResolver.class)\n\t\t\t\t\t.filter(resolver -> resolver.supportsParameter(parameterContext, extensionContext.get(resolver)))\n\t\t\t\t\t.toList();\n\t\t\t// @formatter:on\n\n\t\t\tif (matchingResolvers.isEmpty()) {\n\t\t\t\tthrow new ParameterResolutionException(\n\t\t\t\t\t\"No ParameterResolver registered for parameter [%s] in %s [%s].\".formatted(\n\t\t\t\t\t\tparameterContext.getParameter(), asLabel(executable), executable.toGenericString()));\n\t\t\t}\n\n\t\t\tif (matchingResolvers.size() > 1) {\n\t\t\t\t// @formatter:off\n\t\t\t\tString resolvers = matchingResolvers.stream()\n\t\t\t\t\t\t.map(StringUtils::defaultToString)\n\t\t\t\t\t\t.collect(joining(\", \"));\n\t\t\t\t// @formatter:on\n\t\t\t\tthrow new ParameterResolutionException(\n\t\t\t\t\t\"Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s\".formatted(\n\t\t\t\t\t\tparameterContext.getParameter(), asLabel(executable), executable.toGenericString(), resolvers));\n\t\t\t}\n\n\t\t\tParameterResolver resolver = matchingResolvers.get(0);\n\t\t\tObject value = resolver.resolveParameter(parameterContext, extensionContext.get(resolver));\n\t\t\tvalidateResolvedType(parameterContext.getParameter(), value, executable, resolver);\n\n\t\t\tlogger.trace(\n\t\t\t\t() -> \"ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] in %s [%s].\".formatted(\n\t\t\t\t\tresolver.getClass().getName(), (value != null ? value.getClass().getTypeName() : null),\n\t\t\t\t\tparameterContext.getParameter(), asLabel(executable), executable.toGenericString()));\n\n\t\t\treturn value;\n\t\t}\n\t\tcatch (ParameterResolutionException ex) {\n\t\t\tthrow ex;\n\t\t}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java#L127-L163","documentation":"Thrown as ParameterResolutionException when two or more ParameterResolver extensions report supportsParameter(...) == true for the same parameter. JUnit refuses to guess which resolver wins and aborts the invocation listing every competing resolver.","triggerScenarios":"matchingResolvers.size() > 1 after filtering the extension registry - e.g. two extensions both claim the same parameter type. The message enumerates them via StringUtils.defaultToString for each.","commonSituations":"Two libraries both register a resolver for the same type (e.g. a generic Object resolver, two TestInfo-style extensions); a developer writes a custom resolver that overlaps with a built-in (TestInfo, TempDir) one; duplicate @ExtendWith on class and field.","solutions":["Make the custom resolver's supportsParameter more specific so it stops claiming parameters owned by other resolvers (narrow by annotation, type, position).","Disable one of the competing resolvers via junit.jupiter.execution.extensions.enabled.extension.types filtering.","Remove the duplicate registration (e.g. @ExtendWith present on both the class and a base class)."],"exampleFix":"// before\nclass WideResolver implements ParameterResolver {\n    public boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {\n        return true; // claims everything, conflicts with built-ins\n    }\n}\n// after\nclass MyServiceResolver implements ParameterResolver {\n    public boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {\n        return pc.getParameter().getType() == MyService.class;\n    }\n}","handlingStrategy":"validation","validationCode":"long count = Stream.of(MyTest.class, MyTest.class.getSuperclass())\n    .flatMap(c -> Stream.of(c.getAnnotations()))\n    .filter(a -> a instanceof ExtendWith)\n    .flatMap(a -> Stream.of(((ExtendWith) a).value()))\n    .filter(c -> ParameterResolver.class.isAssignableFrom(c))\n    .count();\nif (count > 1) throw new IllegalStateException(\"multiple ParameterResolvers detected\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Narrow custom ParameterResolver.supportsParameter to a single type/annotation/position.","Avoid duplicating @ExtendWith on class and base class.","Use junit.jupiter.execution.extensions.enabled.extension.types to disable overlapping resolvers."],"tags":["parameter-resolution","parameter-resolver","conflict","extension"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}