junit-team/junit5 · error · ParameterResolutionException

Failed to resolve parameter [%s] in %s [%s]

Error message

Failed to resolve parameter [%s] in %s [%s]

What it means

Thrown by ParameterResolutionUtils.resolveParameter() when the single matching ParameterResolver's resolveParameter() throws a non-ParameterResolutionException throwable. The engine rethrows ParameterResolutionException as-is but wraps other throwables (appending their message) so parameter-resolution failures are uniformly typed.

Source

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

					resolver.getClass().getName(), (value != null ? value.getClass().getTypeName() : null),
					parameterContext.getParameter(), asLabel(executable), executable.toGenericString()));

			return value;
		}
		catch (ParameterResolutionException ex) {
			throw ex;
		}
		catch (Throwable throwable) {
			UnrecoverableExceptions.rethrowIfUnrecoverable(throwable);

			String message = "Failed to resolve parameter [%s] in %s [%s]".formatted(parameterContext.getParameter(),
				asLabel(executable), executable.toGenericString());

			if (StringUtils.isNotBlank(throwable.getMessage())) {
				message += ": " + throwable.getMessage();
			}

			throw new ParameterResolutionException(message, throwable);
		}
	}

	private static void validateResolvedType(Parameter parameter, @Nullable Object value, Executable executable,
			ParameterResolver resolver) {

		Class<?> type = parameter.getType();

		// Note: null is permissible as a resolved value but only for non-primitive types.
		if (!isAssignableTo(value, type)) {
			String message;
			if (value == null && type.isPrimitive()) {
				message = """
						ParameterResolver [%s] resolved a null value for parameter [%s] \
						in %s [%s], but a primitive of type [%s] is required.""".formatted(
					resolver.getClass().getName(), parameter, asLabel(executable), executable.toGenericString(),
					type.getName());
			}

View on GitHub (pinned to 956246301e)

Solutions

  1. Inspect getCause() — it is the original throwable thrown by the resolver.
  2. Fix the resolver's internal failure (external dependency, reflective access, NPE).
  3. If the resolver cannot resolve, throw a ParameterResolutionException directly so the message is not double-wrapped.
  4. For module/reflective access errors, add the appropriate --add-opens to the test JVM args.

Example fix

// before
public Object resolveParameter(ParameterContext pc, ExtensionContext ec) {
    return service.load(pc); // service throws -> wrapped
}
// after
public Object resolveParameter(ParameterContext pc, ExtensionContext ec) {
    try { return service.load(pc); }
    catch (ServiceUnavailableException e) {
        throw new ParameterResolutionException("Cannot load data for " + pc.getParameter(), e);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the resolver can resolve outside the test
Object value;
try { value = resolver.resolveParameter(pc, ctx); }
catch (Throwable t) { throw new IllegalStateException("Resolver throws for " + pc.getParameter(), t); }

Try / catch

try {
    // test runs
} catch (ParameterResolutionException e) {
    Throwable root = e.getCause(); // original from resolver
    log.error("resolver failed: {}", root);
}

Prevention

When it happens

Trigger: A ParameterResolver.resolveParameter() implementation that throws — e.g. it queries a database/service that is down, performs reflective access that hits an IllegalAccessException, or has a bug that raises a NullPointerException.

Common situations: A resolver that loads test data from an external source which is unreachable; a resolver using reflection on a sealed/inaccessible type under Java module restrictions; a resolver with a null-handling bug triggered by a specific parameter shape.

Related errors


AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04). Data as JSON: /data/errors/90c3043a7b91c88b.json. Report an issue: GitHub.