{"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/956246301e03d757539f7b76dd5a91f298637563/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java#L56-L92","documentation":"Thrown by TypedArgumentConverter.convert() when the source argument is not an instance of the converter's declared sourceType. TypedArgumentConverter<S, T> is parameterized by a fixed source and target type; if the actual argument at runtime does not match S, the converter rejects it with this ArgumentConversionException.","triggerScenarios":"A custom TypedArgumentConverter<String, Integer> applied via @ConvertMyConverter to a parameterized test parameter, but the argument source provides a non-String value (e.g., an Integer, enum, or POJO from a @MethodSource). The converter's isInstance check fails.","commonSituations":"Writing a TypedArgumentConverter<String, MyType> and using it with a @MethodSource that provides non-String objects. Reusing a converter designed for String inputs on a source that provides typed objects. Changing the argument source type without updating the converter's sourceType generic.","solutions":["Ensure the arguments source provides values of the type declared as the converter's sourceType (e.g., String for a TypedArgumentConverter<String, T>)","If the source type varies, use a general ArgumentConverter or SimpleArgumentConverter instead of TypedArgumentConverter","Change the converter's sourceType generic parameter to match the actual runtime argument type","If using @MethodSource, provide Arguments.of(stringValue) instead of Arguments.of(typedObject)"],"exampleFix":"// before\nclass StringToIdConverter extends TypedArgumentConverter<String, Id> {\n    // ...\n}\n@ParameterizedTest\n@MethodSource(\"provider\")\nvoid test(@ConvertWith(StringToIdConverter.class) Id id) { }\nstatic Stream<Arguments> provider() {\n    return Stream.of(Arguments.of(123)); // Integer, but converter expects String\n}\n\n// after\nstatic Stream<Arguments> provider() {\n    return Stream.of(Arguments.of(\"id-123\")); // String matches converter sourceType\n}","handlingStrategy":"type-guard","validationCode":"// Check source type compatibility before the converter runs:\nClass<?> sourceType = String.class; // the converter's declared source type\nif (source != null && !sourceType.isInstance(source)) {\n    throw new IllegalStateException(\n        \"Expected \" + sourceType + \" but got \" + source.getClass());\n}","typeGuard":"// Guard before converting:\nif (source instanceof String s) {\n    // safe to apply TypedArgumentConverter<String, T>\n} else {\n    throw new IllegalArgumentException(\n        \"Converter expects String but received \" + (source == null ? \"null\" : source.getClass()));\n}","tryCatchPattern":"try {\n    // @ConvertWith(MyConverter.class) on the parameter\n} catch (ArgumentConversionException e) {\n    if (e.getMessage().contains(\"cannot convert objects of type\")) {\n        // source type mismatch — fix the arguments source\n    }\n    throw e;\n}","preventionTips":["Match the arguments source type with the converter's declared sourceType generic parameter","Use SimpleArgumentConverter or a general ArgumentConverter if the source type varies","Document the expected source type in the converter's class Javadoc","Test converters with all source types that the arguments provider can produce"],"tags":["argument-converter","typed-converter","type-mismatch","parameterized-test","junit-jupiter-params"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}