{"record":{"id":"1c180f0e54d5c2e6","repo":"quarkusio/quarkus","slug":"unable-to-derive-the-service-interface-for-the-gen","errorCode":null,"errorMessage":"Unable to derive the service interface for the generated Mutiny client: ${generatedClient}","messagePattern":"Unable to derive the service interface for the generated Mutiny client: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java","lineNumber":143,"sourceCode":"    void discoverInjectedClients(BeanDiscoveryFinishedBuildItem beanDiscovery,\n            BuildProducer<GrpcClientBuildItem> clients,\n            CombinedIndexBuildItem index) {\n\n        Map<String, GrpcClientBuildItem> items = new HashMap<>();\n\n        // Collect a map of service interface name to the generated client class\n        Map<DotName, DotName> generatedClients = new HashMap<>();\n        for (ClassInfo generatedClient : index.getIndex().getKnownDirectImplementors(GrpcDotNames.MUTINY_CLIENT)) {\n            // Mutiny client implements MutinyClient and the service interface\n            DotName serviceInterface = null;\n            for (DotName name : generatedClient.interfaceNames()) {\n                if (!name.equals(GrpcDotNames.MUTINY_CLIENT)) {\n                    serviceInterface = name;\n                    break;\n                }\n            }\n            if (serviceInterface == null) {\n                throw new IllegalStateException(\n                        \"Unable to derive the service interface for the generated Mutiny client: \" + generatedClient);\n            }\n            generatedClients.put(serviceInterface, generatedClient.name());\n        }\n\n        for (InjectionPointInfo injectionPoint : beanDiscovery.getInjectionPoints()) {\n            AnnotationInstance clientAnnotation = injectionPoint.getRequiredQualifier(GrpcDotNames.GRPC_CLIENT);\n            if (clientAnnotation == null) {\n                continue;\n            }\n            Set<String> registeredInterceptors = getRegisteredInterceptors(injectionPoint);\n\n            String clientName;\n            AnnotationValue clientNameValue = clientAnnotation.value();\n            if (clientNameValue == null || clientNameValue.asString().equals(GrpcClient.ELEMENT_NAME)) {\n                // Determine the service name from the annotated element\n                if (clientAnnotation.target().kind() == Kind.FIELD) {\n                    clientName = clientAnnotation.target().asField().name();","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java#L125-L161","documentation":"During gRPC client generation, Quarkus scans the @GrpcClient-annotated injection point's type for the @MutinyClient annotation to determine which service interface the generated Mutiny client implements. If the generated client class carries no annotation other than @MutinyClient (so no service interface can be derived), the deployment fails. This usually means the class being injected is not a properly generated Mutiny gRPC client.","triggerScenarios":"A bean declares @Inject @GrpcClient SomeClient where SomeClient is annotated with @MutinyClient but no additional annotation naming the service interface; i.e. the type cannot be mapped back to a gRPC service interface during discoverInjectedClients.","commonSituations":"Hand-written classes annotated with @MutinyClient by mistake; injection of the wrong generated type after regenerating stubs; upgrading Quarkus or the gRPC code generator so the generated client no longer carries the expected service-interface annotation; copy-pasting a client class name that does not exist in the generated sources.","solutions":["Inject the generated Mutiny service interface (e.g. Greeter from the .proto, or use @GrpcClient with the named client) instead of a custom class","Verify the stubs are generated by Quarkus's protobuf codegen (mvn compile) and the class actually has both @MutinyClient and the service interface annotation","Check that the @GrpcClient value or annotated type matches a service defined in your .proto files","Clean and rebuild so generated sources are up to date"],"exampleFix":"// before\n@Inject @GrpcClient MyCustomClient client;\n\n// after\n@Inject @GrpcClient(\"hello-service\") Greeter greeter;","handlingStrategy":"validation","validationCode":"// before injecting, check the type maps to a generated Mutiny client service interface\nif (!(client instanceof io.quarkus.grpc.runtime.MutinyGrpc) && !isGeneratedMutinyClient(client.getClass())) {\n    throw new IllegalArgumentException(\"Use the generated service interface, not \" + client.getClass());\n}","typeGuard":"static boolean isGeneratedMutinyClient(Class<?> c) {\n    return c != null && java.util.Arrays.stream(c.getAnnotations())\n        .anyMatch(a -> a.annotationType().getName().endsWith(\"MutinyClient\"));\n}","tryCatchPattern":null,"preventionTips":["Always inject the interface generated from your .proto, not hand-written classes","Run ./mvnw clean compile so generated sources exist before coding against them","Keep the Quarkus gRPC codegen plugin version aligned with your Quarkus BOM"],"tags":["grpc","cdi","quarkus-build"],"backgroundTag":"grpc-client-injection-failure","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"}