{"record":{"id":"4fcee175dbc88c87","repo":"quarkusio/quarkus","slug":"targettype-getname-has-no-string-constructor","errorCode":null,"errorMessage":"${targetType.getName()} has no String constructor","messagePattern":"(.+?) has no String constructor","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/TypeConverter.java","lineNumber":236,"sourceCode":"\n    /**\n     * @param <T> type\n     * @param source source string\n     * @param targetType target type\n     * @return object instance of type T\n     * @throws IllegalArgumentException if not suitable constructor was found\n     * @throws InstantiationException if the underlying constructor represents an abstract class\n     * @throws IllegalAccessException if the underlying constructor is not accessible\n     * @throws InvocationTargetException if the underlying constructor throws exception\n     */\n    private static <T> T getTypeViaStringConstructor(String source, Class<T> targetType) {\n        T result = null;\n        Constructor<T> c = null;\n\n        try {\n            c = targetType.getDeclaredConstructor(String.class);\n        } catch (NoSuchMethodException e) {\n            throw new IllegalArgumentException((targetType.getName() + \" has no String constructor\"), e);\n        }\n\n        try {\n            result = c.newInstance(source);\n        } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n        return result;\n    }\n}\n","sourceCodeStart":218,"sourceCodeEnd":247,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/TypeConverter.java#L218-L247","documentation":"TypeConverter.convert() maps a String to a target type by reflection. It requires the target class to expose a public/no-arg-access constructor accepting a single String; if getDeclaredConstructor(String.class) fails, this IllegalArgumentException is thrown. The library uses it for generic String->T conversion (e.g. header/param conversion), so any type without a String constructor simply cannot be converted this way.","triggerScenarios":"Calling TypeConverter.getType() (via getTypeViaStringConstructor) with a targetType that has no constructor taking a single String, e.g. converting to a primitive wrapperless custom class, an interface, or a class with only (int) or (OtherType) constructors.","commonSituations":"Custom header/cookie/path parameter types in JAX-RS that lack a String constructor or static fromString/valueOf method; refactoring a class and removing its String constructor while it is still used as a REST parameter type.","solutions":["Add a public constructor accepting a single String to the target type","Add a public static valueOf(String) or fromString(String) factory method if the conversion utility supports it","Convert manually before calling the converter, or use a different converter supporting the type","If the type is under your control and should not be string-convertible, stop using TypeConverter for it"],"exampleFix":"// before\npublic class PageParam {\n    public PageParam(int number) { this.number = number; }\n}\n// after\npublic class PageParam {\n    public PageParam(String value) { this.number = Integer.parseInt(value); }\n}","handlingStrategy":"type-guard","validationCode":"boolean hasStringConstructor(Class<?> t) {\n    try { t.getDeclaredConstructor(String.class); return true; }\n    catch (NoSuchMethodException e) { return false; }\n}\n// call: if (!hasStringConstructor(targetType)) throw new IllegalStateException(targetType + \" not string-convertible\");","typeGuard":"static boolean isStringConvertible(Class<?> t) {\n    if (t.isInterface() || t.isPrimitive()) return false;\n    try { t.getDeclaredConstructor(String.class); return true; }\n    catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n    T value = converter.getType(targetType, raw);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().endsWith(\"has no String constructor\")) {\n        value = fallbackConvert(targetType, raw); // custom converter\n    } else throw e;\n}","preventionTips":["Give every REST parameter/header/cookie type a public String constructor","Prefer static fromString(String)/valueOf(String) factory conventions (JAX-RS standard)","Write a startup test that reflects over all custom param types for String constructors","Avoid raw custom classes in generic conversion utilities"],"tags":["reflection","type-conversion","resteasy-reactive"],"backgroundTag":"missing-string-constructor","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}