{"record":{"id":"aabc6e20aed0b379","repo":"quarkusio/quarkus","slug":"subresource-method-returns-an-invalid-type-me","errorCode":null,"errorMessage":"Subresource method returns an invalid type: \" + method.returnType().name()","messagePattern":"Subresource method returns an invalid type: \" \\+ method\\.returnType\\(\\)\\.name\\(\\)","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java","lineNumber":111,"sourceCode":"                if (blockingAnnotation.target().annotation(CLIENT_EXCEPTION_MAPPER) == null) {\n                    offendingBlockingAnnotations.add(blockingAnnotation);\n                }\n            }\n        }\n        if (!offendingBlockingAnnotations.isEmpty()\n                || classInfo.annotationsMap().get(ResteasyReactiveDotNames.NON_BLOCKING) != null) {\n            log.warn(\n                    \"'@Blocking' and '@NonBlocking' annotations are not necessary (or supported) on REST Client interfaces. Offending class is '\"\n                            + classInfo.name()\n                            + \"'. Whether or not the call blocks the calling thread depends on the return type of the method - returning 'Uni', 'Multi' or 'CompletionStage' results in the implementation being non-blocking.\");\n        }\n    }\n\n    @Override\n    protected void handleClientSubResource(ResourceMethod resourceMethod, MethodInfo method, IndexView index) {\n        ClassInfo subResourceClass = index.getClassByName(method.returnType().name());\n        if (subResourceClass == null) {\n            throw new IllegalStateException(\"Subresource method returns an invalid type: \" + method.returnType().name());\n        }\n\n        List<ResourceMethod> endpoints = createEndpoints(subResourceClass, subResourceClass,\n                new HashSet<>(), new HashSet<>(), new HashSet<>(),\n                \"\", false);\n        resourceMethod.setSubResourceMethods(endpoints);\n    }\n\n    @Override\n    protected ResourceMethod createResourceMethod(MethodInfo info, ClassInfo actualEndpointClass,\n            Map<String, Object> methodContext) {\n\n        return new ResourceMethod();\n    }\n\n    @Override\n    protected boolean handleBeanParam(ClassInfo actualEndpointInfo, Type paramType, MethodParameter[] methodParameters, int i,\n            Set<String> fileFormNames) {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/client/processor/src/main/java/org/jboss/resteasy/reactive/client/processor/scanning/ClientEndpointIndexer.java#L93-L129","documentation":"ClientEndpointIndexer.handleClientSubResource throws this when a client interface subresource method returns a type that is not present in the build-time index. The indexer must scan the returned class to discover its own sub-endpoints, and ClassInfo for it could not be found (not indexed, not on the Jandex index, or not a class).","triggerScenarios":"A REST Client interface method (a subresource locator) returns a type that is: a primitive, a generic/parameterized type not resolvable to a class, generated at runtime, or in a dependency not part of the Jandex index used during client build-step processing.","commonSituations":"Returning Optional<SubResource> or List<SubResource> from a locator method; subresource interface living in a jar without a Jandex index (missing jandex-maven-plugin processing); Quarkus version change altering which types get indexed.","solutions":["Make the subresource method return a concrete, indexed interface or class — not a wrapper type like Optional or a collection.","Ensure the module containing the subresource type is indexed: add the jandex-maven-plugin (process goal) or a META-INF/jandex.idx to the dependency jar.","If the type is in a third-party jar, add quarkus.index-dependency.<name>.group-id/artifact config entries so Quarkus indexes it.","Restructure so the client method is a normal endpoint (returning response types) rather than a subresource locator."],"exampleFix":"// before\n@Path(\"/items\")\nOptional<ItemSubResource> getItems();\n// after\n@Path(\"/items\")\nItemSubResource getItems();","handlingStrategy":"validation","validationCode":"// Subresource locator methods must return a bare, concrete class/interface name\nMethod m = clientInterface.getMethod(\"getItems\");\nType rt = m.getGenericReturnType();\nif (rt instanceof ParameterizedType) {\n  throw new IllegalStateException(\"Subresource locator must not return a generic type: \" + rt);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Return plain interface/class types from subresource locator methods","Index every dependency containing client types (jandex plugin or quarkus.index-dependency.*)","Never wrap subresource return types in Optional/Collection"],"tags":["rest-client","subresource","jandex","build-time"],"backgroundTag":"class-not-indexed","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"}