junit-team/junit5 · error · ParameterResolutionException
Discovered multiple competing ParameterResolvers for paramet
Error message
Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s
What it means
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.
Source
Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java:145
// @formatter:off
List<ParameterResolver> matchingResolvers = extensionRegistry.stream(ParameterResolver.class)
.filter(resolver -> resolver.supportsParameter(parameterContext, extensionContext.get(resolver)))
.toList();
// @formatter:on
if (matchingResolvers.isEmpty()) {
throw new ParameterResolutionException(
"No ParameterResolver registered for parameter [%s] in %s [%s].".formatted(
parameterContext.getParameter(), asLabel(executable), executable.toGenericString()));
}
if (matchingResolvers.size() > 1) {
// @formatter:off
String resolvers = matchingResolvers.stream()
.map(StringUtils::defaultToString)
.collect(joining(", "));
// @formatter:on
throw new ParameterResolutionException(
"Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s".formatted(
parameterContext.getParameter(), asLabel(executable), executable.toGenericString(), resolvers));
}
ParameterResolver resolver = matchingResolvers.get(0);
Object value = resolver.resolveParameter(parameterContext, extensionContext.get(resolver));
validateResolvedType(parameterContext.getParameter(), value, executable, resolver);
logger.trace(
() -> "ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] in %s [%s].".formatted(
resolver.getClass().getName(), (value != null ? value.getClass().getTypeName() : null),
parameterContext.getParameter(), asLabel(executable), executable.toGenericString()));
return value;
}
catch (ParameterResolutionException ex) {
throw ex;
}View on GitHub (pinned to 956246301e)
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.
Example fix
// before — resolver too broad
public boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {
return true; // claims everything -> conflict with other resolvers
}
// after
public boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {
return pc.isAnnotated(MyAnnotation.class);
} Defensive patterns
Strategy: validation
Validate before calling
// Detect multiple supporting resolvers up front
long count = registeredResolvers.stream().filter(r -> r.supportsParameter(pc, ctx)).count();
if (count > 1) throw new IllegalStateException("Competing resolvers for " + pc.getParameter()); Type guard
static boolean exactlyOneResolver(Parameter p, List<ParameterResolver> resolvers, ExtensionContext ctx) {
ParameterContext pc = new DefaultParameterContext(p, 0, null);
return resolvers.stream().filter(r -> r.supportsParameter(pc, ctx)).count() == 1;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No ParameterResolver registered for parameter [%s] in %s [%s
- Failed to resolve parameter [%s] in %s [%s]
- Failed to publish path
- Failed to create output directory
- The following TestInstanceFactory extensions were registered
AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04).
Data as JSON: /data/errors/e129b7d9771f95bc.json.
Report an issue: GitHub.