junit-team/junit5 · error · ParameterResolutionException

ParameterResolver [%s] resolved a value of type [%s] for par

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 ParameterResolutionUtils.validateResolvedType() when a ParameterResolver returns a non-null value whose type is not assignment-compatible with the declared parameter type (and the parameter is not a primitive). The message names the resolver, the actual value type, the parameter, the executable, and the required type.

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 956246301e)

Solutions

  1. Make the resolver return a value whose type matches (or is a subtype of) the declared parameter type.
  2. Register/fix an ArgumentConverter (via @ConvertWith) so @CsvSource/@EnumSource data converts to the parameter type.
  3. Inspect the message — it states both the actual type and the required type — and align them.
  4. For generic/boxing mismatches, narrow the parameter type or wrap the value appropriately.

Example fix

// before
@ParameterizedTest
@CsvSource({ "1,2" })
void test(Path p) { ... } // String "1,2" not assignable to Path

// after
@ParameterizedTest
@CsvSource({ "1,2" })
void test(String s) { ... } // matching type
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate resolved value is assignable before relying on the test
Object value = resolver.resolveParameter(pc, ctx);
if (value != null && !pc.getParameter().getType().isAssignableFrom(value.getClass())) {
    throw new IllegalStateException("Type mismatch: " + value.getClass() + " vs " + pc.getParameter().getType());
}

Type guard

static boolean isAssignmentCompatible(Object value, Parameter p) {
    return value == null || p.getType().isAssignableFrom(value.getClass());
}

Prevention

When it happens

Trigger: A ParameterResolver.resolveParameter() returns an object whose class is not assignable to the parameter's declared type — e.g. returning a String for a Path parameter, an Integer for a List parameter, or a custom argument converter producing the wrong type.

Common situations: A custom argument converter/resolver returning the wrong type after a refactor; @CsvSource parsing a column as a String when the parameter expects a typed value and no ArgumentConverter is registered; a resolver that returns a raw type incompatible with a generic parameter under strict type checks.

Related errors


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