{"record":{"id":"4ad263f3b3b27fed","repo":"quarkusio/quarkus","slug":"multipart-responses-can-only-be-mapped-to-non-gene","errorCode":null,"errorMessage":"multipart responses can only be mapped to non-generic classes, got \" + result + \" of type: \" + result.kind()","messagePattern":"multipart responses can only be mapped to non-generic classes, got \" \\+ result \\+ \" of type: \" \\+ result\\.kind\\(\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java","lineNumber":1461,"sourceCode":"                    }\n                }\n            }\n        }\n    }\n\n    private ClassInfo returnTypeAsClass(MethodInfo jandexMethod, IndexView index) {\n        Type result = jandexMethod.returnType();\n        if (result.kind() == PARAMETERIZED_TYPE) {\n            if (result.name().equals(COMPLETION_STAGE) || result.name().equals(UNI)) {\n                Type firstArgument = result.asParameterizedType().arguments().get(0);\n                if (firstArgument.kind() == CLASS) {\n                    return index.getClassByName(firstArgument.asClassType().name());\n                }\n            }\n        } else if (result.kind() == CLASS) {\n            return index.getClassByName(result.asClassType().name());\n        }\n        throw new IllegalArgumentException(\"multipart responses can only be mapped to non-generic classes, \" +\n                \"got \" + result + \" of type: \" + result.kind());\n    }\n\n    /**\n     * Tries to figure out the real type of type variable present in the given type, using the provided\n     * ownerIdentifierTypeLookupMap. Currently, types of kind PARAMETERIZED_TYPE and TYPE_VARIABLE are handled.\n     *\n     * @param type the type to resolve\n     * @param ownerIdentifierTypeLookupMap the lookup map type variable -> real type\n     * @param declaration The jandex declaration where the type was used.\n     * @return A type where all type variables are resolved, never null.\n     * @throws IllegalArgumentException if a type variable could not be resolved\n     */\n    private Type resolveType(Type type,\n            Map<String, Type> ownerIdentifierTypeLookupMap, Declaration declaration) {\n        if (type.kind() == PARAMETERIZED_TYPE) {\n\n            ParameterizedType parameterizedReturnType = type.asParameterizedType();","sourceCodeStart":1443,"sourceCodeEnd":1479,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java#L1443-L1479","documentation":"For multipart responses, the generator must map the result type to a concrete non-generic class so it can index it and generate field fillers. If the resolved return type is a type variable, primitive, array-of-generic, or otherwise not a CLASS, it throws an IllegalArgumentException reporting the type and its kind.","triggerScenarios":"Declaring a REST client method returning a generic type (e.g. T, Wrapper<T> where T is a method type variable) with multipart response handling, where resolveType cannot reduce it to a plain class.","commonSituations":"Generic client interfaces implemented for multiple types; using List<T> or a raw type variable as multipart return; inheritance-based generic DTOs.","solutions":["Change the client method to return a concrete non-generic class for multipart responses","If generics are needed, subclass with a concrete type argument (class StringWrapper extends Wrapper<String>) so resolution yields a CLASS","Inspect the multipart method signature and remove type variables"],"exampleFix":"// before\n<T> T getMultipart();\n// after\nMultipartBody getMultipart();","handlingStrategy":"validation","validationCode":"static void assertNonGenericReturn(java.lang.reflect.Method m) { Type r = m.getGenericReturnType(); if (r instanceof TypeVariable || (r instanceof ParameterizedType pt && Arrays.stream(pt.getActualTypeArguments()).anyMatch(a -> a instanceof TypeVariable))) throw new IllegalStateException(\"Multipart return must be non-generic: \" + r); }","typeGuard":"boolean isConcreteReturn(java.lang.reflect.Method m) { return !(m.getGenericReturnType() instanceof TypeVariable); }","tryCatchPattern":"try { client.get(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"non-generic classes\")) { log.error(\"Return a concrete class for multipart\"); } throw e; }","preventionTips":["Return concrete classes from multipart client methods","Subclass generic wrappers with concrete type arguments","Avoid raw type variables in client interfaces","Generate/test the client during CI to fail fast"],"tags":["quarkus","rest-client","multipart","generics","build-time"],"backgroundTag":"unsupported-generic-type","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}