{"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/956246301e03d757539f7b76dd5a91f298637563/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java#L127-L163","documentation":"Thrown by ParameterResolutionUtils.resolveParameter() when two or more ParameterResolvers claim the same parameter (supportsParameter returns true for more than one resolver). JUnit requires a single owner per parameter to avoid ambiguity, so the conflict is reported as a ParameterResolutionException listing every competing resolver.","triggerScenarios":"Registering two extensions whose ParameterResolvers both support the same parameter type/context — e.g. two @RegisterExtension fields that resolve the same type, or a third-party resolver overlapping with a custom one, or accidentally registering the same extension twice.","commonSituations":"Combining two mocking frameworks that both resolve a parameter; a custom resolver that is too broad (returns true from supportsParameter for any type); duplicate registration of @RegisterExtension via inheritance from a base class plus the subclass.","solutions":["Narrow one resolver's supportsParameter() so only one claims the parameter (e.g. check an annotation or exact type).","Remove the duplicate registration — search for @RegisterExtension fields and @ExtendWith meta-annotations across the class hierarchy.","If using two frameworks that overlap, restrict each to distinct parameter types/annotations."],"exampleFix":"// before — resolver too broad\npublic boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {\n    return true; // claims everything -> conflict with other resolvers\n}\n// after\npublic boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {\n    return pc.isAnnotated(MyAnnotation.class);\n}","handlingStrategy":"validation","validationCode":"// Detect multiple supporting resolvers up front\nlong count = registeredResolvers.stream().filter(r -> r.supportsParameter(pc, ctx)).count();\nif (count > 1) throw new IllegalStateException(\"Competing resolvers for \" + pc.getParameter());","typeGuard":"static boolean exactlyOneResolver(Parameter p, List<ParameterResolver> resolvers, ExtensionContext ctx) {\n    ParameterContext pc = new DefaultParameterContext(p, 0, null);\n    return resolvers.stream().filter(r -> r.supportsParameter(pc, ctx)).count() == 1;\n}","tryCatchPattern":null,"preventionTips":["Narrow supportsParameter() using annotations or exact type checks.","Avoid registering the same extension twice via inheritance.","Do not combine two frameworks that resolve the same parameter type."],"tags":["junit-jupiter","parameter-resolution","extension","conflict"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}