{"record":{"id":"1fc5c94064fe119b","repo":"quarkusio/quarkus","slug":"type-variable-s-of-s-could-not-be-resolved","errorCode":null,"errorMessage":"Type variable %s of %s could not be resolved.","messagePattern":"Type variable (.+?) of (.+?) could not be resolved\\.","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":1493,"sourceCode":"    private Type resolveType(Type type,\n            Map<String, Type> ownerIdentifierTypeLookupMap, Declaration declaration) {\n        if (type.kind() == PARAMETERIZED_TYPE) {\n\n            ParameterizedType parameterizedReturnType = type.asParameterizedType();\n            ParameterizedType.Builder methodReturnTypeBuilder = ParameterizedType.builder(type.name());\n            for (int i = 0; i < parameterizedReturnType.arguments().size(); i++) {\n                Type paramReturnTypeArg = parameterizedReturnType.arguments().get(i);\n                Type resolvedType;\n                if (paramReturnTypeArg.kind() == TYPE_VARIABLE) {\n                    // method returns another subresource, and one of the arguments is a type variable e.g.  Wrapper<T>\n                    resolvedType = ownerIdentifierTypeLookupMap.get(paramReturnTypeArg.asTypeVariable().identifier());\n                    if (resolvedType == null) {\n                        String declarationSite = declaration.toString();\n                        if (declaration.kind() == AnnotationTarget.Kind.METHOD) {\n                            declarationSite = \"method %s in class %s\".formatted(declaration,\n                                    declaration.asMethod().declaringClass());\n                        }\n                        throw new IllegalArgumentException(\n                                \"Type variable %s of %s could not be resolved.\"\n                                        .formatted(paramReturnTypeArg.asTypeVariable().identifier(), declarationSite));\n                    }\n                } else if (paramReturnTypeArg.kind() == PARAMETERIZED_TYPE) {\n                    // parameterized type contains another parameterized type with either a type variable e.g.  Wrapper<List<T>> or without, e.g. Wrapper<List<String>>\n                    resolvedType = resolveType(paramReturnTypeArg, ownerIdentifierTypeLookupMap, declaration);\n                } else {\n                    resolvedType = paramReturnTypeArg;\n                }\n\n                methodReturnTypeBuilder.addArgument(resolvedType);\n            }\n\n            // rewrite parameterized type to reflect the resolved type variable\n            // i.e. Wrapper<String> instead of Wrapper<V>\n            return methodReturnTypeBuilder.build();\n        } else if (type.kind() == TYPE_VARIABLE) {\n            TypeVariable typeVariable = type.asTypeVariable();","sourceCodeStart":1475,"sourceCodeEnd":1511,"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#L1475-L1511","documentation":"While resolving the type arguments of a multipart response's parameterized return type, a nested type variable (e.g. the T in Wrapper<T>) could not be found in the ownerIdentifierTypeLookupMap built from the declaration. The generator cannot synthesize a GenericType without a concrete type, so it throws an IllegalArgumentException including the unresolved identifier and the declaration site.","triggerScenarios":"A client method returns e.g. Wrapper<T> or Result<T, E> where a nested type argument is a type variable that no enclosing declaration binds — e.g. the type variable comes from an unparameterized superclass or interface rather than the method itself.","commonSituations":"Generic base interfaces (Repository<T> with getClient returning T) extended raw; missing explicit type argument in an extends clause; mixing generic helper classes into multipart responses.","solutions":["Bind the type variable: make the declaring class/interface parameterized with a concrete type (interface MyClient extends GenericClient<MultipartBody>)","Change the multipart method return to a fully concrete type","Verify that all type variables used in the return type appear in the method or declaring class signature"],"exampleFix":"// before\nclass MyClient implements GenericClient<T> { T get(); } // raw T\n// after\nclass MyClient implements GenericClient<MultipartBody> { MultipartBody get(); }","handlingStrategy":"validation","validationCode":"static void assertBoundGenerics(Class<?> clientItf) { for (var m : clientItf.getMethods()) { for (var a : ((ParameterizedType) m.getGenericReturnType() instanceof ParameterizedType pt ? pt.getActualTypeArguments() : new Type[0])) { if (a instanceof TypeVariable) throw new IllegalStateException(\"Unbound type var \" + a + \" in \" + m); } } }","typeGuard":"boolean allTypeArgsConcrete(Type t) { return !(t instanceof TypeVariable) && (!(t instanceof ParameterizedType pt) || Arrays.stream(pt.getActualTypeArguments()).allMatch(a -> a instanceof Class || (a instanceof ParameterizedType p && allTypeArgsConcrete(p)))); }","tryCatchPattern":"try { client.fetch(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"could not be resolved\")) { log.error(\"Bind the type variable named in the message\"); } throw e; }","preventionTips":["Parameterize generic base interfaces with concrete types","Never extend a generic client interface raw","Keep type variables bound at the client interface level","Read the exception's declaration site to locate the unbound variable"],"tags":["quarkus","rest-client","generics","type-resolution","build-time"],"backgroundTag":"unresolved-type-variable","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"}