{"record":{"id":"dbde8f0ecb04d7ed","repo":"junit-team/junit5","slug":"s-cannot-convert-objects-of-type-s-only-sourc","errorCode":null,"errorMessage":"%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.","messagePattern":"(.+?) cannot convert objects of type \\[(.+?)\\]\\. Only source objects of type \\[(.+?)\\] are supported\\.","errorType":"exception","errorClass":"ArgumentConversionException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java","lineNumber":74,"sourceCode":"\n\t\treturn convert(source, context.getParameter().getType());\n\t}\n\n\t@Override\n\tpublic final @Nullable Object convert(@Nullable Object source, FieldContext context)\n\t\t\tthrows ArgumentConversionException {\n\n\t\treturn convert(source, context.getField().getType());\n\t}\n\n\tprivate T convert(@Nullable Object source, Class<?> actualTargetType) {\n\t\tif (source == null) {\n\t\t\treturn convert(null);\n\t\t}\n\t\tif (!this.sourceType.isInstance(source)) {\n\t\t\tString message = \"%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.\".formatted(\n\t\t\t\tgetClass().getSimpleName(), source.getClass().getTypeName(), this.sourceType.getTypeName());\n\t\t\tthrow new ArgumentConversionException(message);\n\t\t}\n\t\tif (!ReflectionUtils.isAssignableTo(this.targetType, actualTargetType)) {\n\t\t\tString message = \"%s cannot convert to type [%s]. Only target type [%s] is supported.\".formatted(\n\t\t\t\tgetClass().getSimpleName(), actualTargetType.getTypeName(), this.targetType.getTypeName());\n\t\t\tthrow new ArgumentConversionException(message);\n\t\t}\n\t\treturn convert(this.sourceType.cast(source));\n\t}\n\n\t/**\n\t * Convert the supplied {@code source} object of type {@code S} into an object\n\t * of type {@code T}.\n\t *\n\t * @param source the source object to convert; may be {@code null}\n\t * @return the converted object; may be {@code null} but only if the target\n\t * type is a reference type\n\t * @throws ArgumentConversionException if an error occurs during the\n\t * conversion","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Align the argument source type with the converter's declared sourceType (e.g. ensure CSV/arguments provide String if the converter is TypedArgumentConverter<String,?>).","Update the converter's generic sourceType parameter to match the actual incoming type.","Chain converters or preprocess arguments so the source reaching this converter is the expected type.","Inspect the message: it prints the actual class and expected class to pinpoint the mismatch."],"exampleFix":"// before\nclass StringToInt extends TypedArgumentConverter<String, Integer> { ... }\n@ParameterizedTest\n@ValueSource(ints = 5)\nvoid test(@ConvertWith(StringToInt.class) Integer v) { }\n\n// after\n@ParameterizedTest\n@ValueSource(strings = \"5\")\nvoid test(@ConvertWith(StringToInt.class) Integer v) { }","handlingStrategy":"type-guard","validationCode":"// Verify the source object matches the converter's expected source type before registration\nClass<?> expectedSource = String.class; // example\nif (!expectedSource.isInstance(sourceObject)) {\n    throw new IllegalArgumentException(\"Source must be \" + expectedSource.getName());\n}","typeGuard":"static boolean matchesSourceType(TypedArgumentConverter<?, ?> converter, Object source) {\n    return converter.getSourceType().isInstance(source);\n}","tryCatchPattern":"try {\n    return converter.convert(source, context);\n} catch (ArgumentConversionException e) {\n    if (e.getMessage().contains(\"cannot convert objects of type\")) {\n        // log and reconfigure source provider to yield the expected type\n    }\n    throw e;\n}","preventionTips":["Document the sourceType generic on every TypedArgumentConverter subclass.","Align the argument source provider output type with the converter's sourceType.","Unit-test converters in isolation with the exact source type they will receive."],"tags":["junit-jupiter","argument-conversion","typed-converter","type-mismatch"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}