junit-team/junit5 · error · ConversionException

No built-in converter for source type java.lang.String and t

Error message

No built-in converter for source type java.lang.String and target type ${targetType.getTypeName()}

What it means

ConversionSupport.convert throws ConversionException when no registered StringToObjectConverter handles the target type and the convention-based fallback (a single non-private static factory method or constructor accepting String/CharSequence) does not apply. The target type is unsupported for String conversion.

Source

Thrown at junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java:140

			candidate -> candidate.canConvertTo(targetTypeToUse)).findFirst();
		if (converter.isPresent()) {
			try {
				ClassLoader classLoaderToUse = classLoader != null ? classLoader
						: ClassLoaderUtils.getDefaultClassLoader();
				return (T) converter.get().convert(source, targetTypeToUse, classLoaderToUse);
			}
			catch (Exception ex) {
				if (ex instanceof ConversionException conversionException) {
					// simply rethrow it
					throw conversionException;
				}
				// else
				throw new ConversionException(
					"Failed to convert String \"%s\" to type %s".formatted(source, targetType.getTypeName()), ex);
			}
		}

		throw new ConversionException(
			"No built-in converter for source type java.lang.String and target type " + targetType.getTypeName());
	}

	private static Class<?> toWrapperType(Class<?> targetType) {
		Class<?> wrapperType = getWrapperType(targetType);
		return wrapperType != null ? wrapperType : targetType;
	}

}

View on GitHub (pinned to 956246301e)

Solutions

  1. Register a custom ArgumentConverter via @ConvertWith on the parameter.
  2. Add a single non-private static factory method (e.g. static Person from(String)) or a single-String constructor to the target type.
  3. Change the parameter to String and construct the target object inside the test.

Example fix

// before
@ParameterizedTest
@CsvSource({ "alice,30" })
void test(Person p) { }   // Person has no String factory

// after
@ParameterizedTest
@CsvSource({ "alice,30" })
void test(@ConvertWith(PersonConverter.class) Person p) { }
// or give Person: public static Person from(String csv) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Detect unsupported target types before the test runs.
Class<?> target = Person.class;
boolean hasBuiltIn = List.of(
    Boolean.class, Character.class, Number.class, Class.class,
    java.time.temporal.Temporal.class, java.io.File.class,
    java.nio.file.Path.class, java.nio.charset.Charset.class,
    java.util.UUID.class, java.net.URI.class, java.net.URL.class,
    java.util.Currency.class, java.util.Locale.class)
    .stream().anyMatch(c -> c.isAssignableFrom(target));
boolean singleStringFactory =
    java.util.Arrays.stream(target.getMethods())
        .filter(m -> java.lang.reflect.Modifier.isStatic(m.getModifiers())
            && !java.lang.reflect.Modifier.isPrivate(m.getModifiers())
            && m.getParameterCount() == 1
            && (m.getParameterTypes()[0] == String.class
                || m.getParameterTypes()[0] == CharSequence.class)
            && target.isAssignableFrom(m.getReturnType()))
        .count() == 1;
if (!hasBuiltIn && !singleStringFactory && !target.isEnum()) {
    throw new IllegalStateException(target + " has no String converter; register @ConvertWith");
}

Try / catch

try {
    ConversionSupport.convert(source, targetType, null);
} catch (ConversionException e) {
    if (e.getMessage().startsWith("No built-in converter")) {
        // add a custom ArgumentConverter or a single-String factory/constructor on the target type
    } else throw e;
}

Prevention

When it happens

Trigger: A parameterized-test parameter of an arbitrary type that has no built-in converter, no single-String static factory, and no single-String constructor - e.g. a POJO with multiple or no String-based factories.

Common situations: Adding a new domain-type parameter to a @ParameterizedTest without a converter; type whose factory methods are ambiguous (more than one candidate, which the fallback ignores).

Related errors


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