junit-team/junit5 · error · ParameterResolutionException

ParameterResolver [ ] resolved a value of type [ ] for…

Error message

ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] in %s [%s], but a value assignment compatible with [%s] is required.

What it means

Thrown by validateResolvedType when the value returned by a ParameterResolver.resolveParameter is not assignable to the parameter type. There is a separate branch for the special case where the parameter is primitive and the resolver returned null; otherwise the resolver is named and the resolved type is reported alongside the required type.

Solutions

  1. Make the resolver branch on pc.getParameter().getType() and return the correct concrete type for that parameter.
  2. Never return null for primitive parameters - resolve to the primitive default (0, 0L, false) or a real value.
  3. If the value is genuinely optional, change the parameter to the boxed wrapper type (Integer instead of int).

Example fix

// before
@Override public Object resolveParameter(ParameterContext pc, ExtensionContext ec) {
    return "42"; // String for an int parameter
}
// after
@Override public Object resolveParameter(ParameterContext pc, ExtensionContext ec) {
    return Integer.parseInt("42");
}
Defensive patterns

Strategy: type-guard

Validate before calling

Object value = resolver.resolveParameter(pc, ec);
Class<?> t = pc.getParameter().getType();
if (!t.isPrimitive() && value != null && !t.isInstance(value)) {
    throw new IllegalStateException("Resolver returned " + value.getClass() + " for " + t);
}
if (t.isPrimitive() && value == null) {
    throw new IllegalStateException("null returned for primitive " + t);
}

Type guard

Object v = resolver.resolveParameter(pc, ec);
Class<?> t = pc.getParameter().getType();
boolean ok = (t.isPrimitive()) ? v != null && isAssignableTo(v, t) : (v == null || t.isInstance(v));
if (!ok) throw new IllegalStateException("type mismatch for " + t);

Prevention

When it happens

Trigger: validateResolvedType(parameter, value, ...) is called right after resolveParameter; if !isAssignableTo(value, type) the resolver produced the wrong type - e.g. resolver returns a String for an Integer parameter, or returns null for an int primitive parameter.

Common situations: Custom resolver returns the cached/wrong object without checking parameter type; resolver returns null for a primitive parameter (int, long, boolean) where null is not permissible; resolver returns a parent type rather than the requested subtype.

Related errors


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

Appendix: source

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

		// 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());
			}
			else {
				message = """
						ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] \
						in %s [%s], but a value assignment compatible with [%s] is required.""".formatted(
					resolver.getClass().getName(), (value != null ? value.getClass().getTypeName() : null), parameter,
					asLabel(executable), executable.toGenericString(), type.getTypeName());
			}

			throw new ParameterResolutionException(message);
		}
	}

	private static String asLabel(Executable executable) {
		return executable instanceof Constructor ? "constructor" : "method";
	}

	private ParameterResolutionUtils() {
	}

}

View on GitHub (pinned to f070c699a0)