junit-team/junit5 · error · ArgumentConversionException

cannot convert objects of type [ ]. Only source objects of…

Error message

%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.

What it means

Thrown by TypedArgumentConverter when the incoming source object is not an instance of the converter's declared sourceType (S). The generic converter is bound to a specific source type at construction; receiving any other runtime type is a contract violation. The message names the actual runtime class and the expected sourceType.

Solutions

  1. Align the argument source type with the converter's declared sourceType (e.g. ensure CSV/arguments provide String if the converter is TypedArgumentConverter<String,?>).
  2. Update the converter's generic sourceType parameter to match the actual incoming type.
  3. Chain converters or preprocess arguments so the source reaching this converter is the expected type.
  4. Inspect the message: it prints the actual class and expected class to pinpoint the mismatch.

Example fix

// before
class StringToInt extends TypedArgumentConverter<String, Integer> { ... }
@ParameterizedTest
@ValueSource(ints = 5)
void test(@ConvertWith(StringToInt.class) Integer v) { }

// after
@ParameterizedTest
@ValueSource(strings = "5")
void test(@ConvertWith(StringToInt.class) Integer v) { }
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify the source object matches the converter's expected source type before registration
Class<?> expectedSource = String.class; // example
if (!expectedSource.isInstance(sourceObject)) {
    throw new IllegalArgumentException("Source must be " + expectedSource.getName());
}

Type guard

static boolean matchesSourceType(TypedArgumentConverter<?, ?> converter, Object source) {
    return converter.getSourceType().isInstance(source);
}

Try / catch

try {
    return converter.convert(source, context);
} catch (ArgumentConversionException e) {
    if (e.getMessage().contains("cannot convert objects of type")) {
        // log and reconfigure source provider to yield the expected type
    }
    throw e;
}

Prevention

When it happens

Trigger: A subclass of TypedArgumentConverter<String, Integer> (for example) is registered via @ConvertWith but the argument source provides a non-String value (e.g. an Integer or a primitive wrapper). The `!this.sourceType.isInstance(source)` guard fires.

Common situations: Registering a typed converter against a parameter whose source data type differs from what the converter expects (CSV providing numbers as Integer vs String). Refactoring a converter's sourceType generic but forgetting to update the parameter source. Combining @ConvertWith with a source provider that yields a different type than the converter declares.

Related errors


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

Appendix: source

Thrown at junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java:74

		return convert(source, context.getParameter().getType());
	}

	@Override
	public final @Nullable Object convert(@Nullable Object source, FieldContext context)
			throws ArgumentConversionException {

		return convert(source, context.getField().getType());
	}

	private T convert(@Nullable Object source, Class<?> actualTargetType) {
		if (source == null) {
			return convert(null);
		}
		if (!this.sourceType.isInstance(source)) {
			String message = "%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.".formatted(
				getClass().getSimpleName(), source.getClass().getTypeName(), this.sourceType.getTypeName());
			throw new ArgumentConversionException(message);
		}
		if (!ReflectionUtils.isAssignableTo(this.targetType, actualTargetType)) {
			String message = "%s cannot convert to type [%s]. Only target type [%s] is supported.".formatted(
				getClass().getSimpleName(), actualTargetType.getTypeName(), this.targetType.getTypeName());
			throw new ArgumentConversionException(message);
		}
		return convert(this.sourceType.cast(source));
	}

	/**
	 * Convert the supplied {@code source} object of type {@code S} into an object
	 * of type {@code T}.
	 *
	 * @param source the source object to convert; may be {@code null}
	 * @return the converted object; may be {@code null} but only if the target
	 * type is a reference type
	 * @throws ArgumentConversionException if an error occurs during the
	 * conversion

View on GitHub (pinned to f070c699a0)