junit-team/junit5 · error · ParameterResolutionException

No ParameterResolver registered for parameter

Error message

No ParameterResolver registered for parameter [%s] in %s [%s].

What it means

Thrown as ParameterResolutionException when no registered ParameterResolver reports supportsParameter(...) == true for a parameter of a test constructor or test/lifecycle method. JUnit Jupiter resolves every parameter via extensions, so an unresolved parameter is fatal for that invocation.

Solutions

  1. Add @RegisterExtension/@ExtendWith for a ParameterResolver that handles the unresolved type.
  2. Switch the parameter to a built-in resolvable type (TestInfo, TestReporter, RepetitionInfo, ExtensionContext, TempDir) and read what you need from it.
  3. Fix a custom resolver's supportsParameter to return true for the relevant parameter context (check annotations, position, declaring executable).

Example fix

// before
@Test
void uses(UserService svc) { } // no resolver
// after - register a resolver that builds it
@RegisterExtension
static final UserServiceResolver resolver = new UserServiceResolver();

static class UserServiceResolver implements ParameterResolver {
    @Override public boolean supportsParameter(ParameterContext pc, ExtensionContext ec) {
        return pc.getParameter().getType() == UserService.class;
    }
    @Override public Object resolveParameter(ParameterContext pc, ExtensionContext ec) {
        return new UserService();
    }
}
Defensive patterns

Strategy: validation

Validate before calling

List<ParameterResolver> resolvers = ServiceLoader.load(ParameterResolver.class).stream()
    .map(p -> p.get())
    .filter(r -> r.supportsParameter(parameterContext, extensionContext))
    .toList();
if (resolvers.isEmpty()) {
    throw new IllegalStateException("No resolver for parameter " + parameterContext.getParameter());
}

Prevention

When it happens

Trigger: resolveParameter filters the extensionRegistry stream of ParameterResolver to those that supportsParameter; if matchingResolvers.isEmpty(), the throw fires. Common with constructor/method parameters that no built-in or registered resolver handles (TestInfo, RepetitionInfo, TestReporter are built-in; arbitrary types need an extension).

Common situations: Asking for a domain object (UserService, RestClient) without a corresponding ParameterResolver; typo in a custom resolver's supportsParameter; a resolver that only handles certain parameter names/positions; using a parameter type supported only when an annotation is present but the annotation was forgotten.

Related errors


AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11). Data as JSON: /api/errors/080d945e97b86419. Report an issue: GitHub.

Appendix: source

Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java:134

		for (int i = start; i < parameters.length; i++) {
			ParameterContext parameterContext = new DefaultParameterContext(parameters[i], i, target);
			values[i] = resolveParameter(parameterContext, executable, extensionContext, extensionRegistry);
		}
		return values;
	}

	private static @Nullable Object resolveParameter(ParameterContext parameterContext, Executable executable,
			ExtensionContextSupplier extensionContext, ExtensionRegistry extensionRegistry) {

		try {
			// @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);

View on GitHub (pinned to f070c699a0)