quarkusio/quarkus · error · IllegalStateException

A gRPC service injection is missing the @GrpcClient qualifie

Error message

A gRPC service injection is missing the @GrpcClient qualifier: ${class}#${field}

What it means

A field of a gRPC service interface type is annotated only with @Inject (no @GrpcClient qualifier). Quarkus-generated clients require @GrpcClient to disambiguate which configured client/service to inject; an unqualified injection cannot be resolved, so deployment fails.

Source

Thrown at extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java:321

    }

    @BuildStep
    public void validateInjectedServiceInterfaces(CombinedIndexBuildItem index,
            // Dummy producer - this build step needs to be executed before the CDI container is initialized
            BuildProducer<UnremovableBeanBuildItem> dummy) {
        // Attempt to detect wrong service interface injection points
        // Note that we cannot use injection points metadata because the build can fail with unsatisfied dependency before
        Set<DotName> serviceInterfaces = new HashSet<>();
        for (ClassInfo serviceInterface : index.getIndex().getKnownDirectImplementors(GrpcDotNames.MUTINY_SERVICE)) {
            serviceInterfaces.add(serviceInterface.name());
        }

        for (AnnotationInstance injectAnnotation : index.getIndex().getAnnotations(DotNames.INJECT)) {
            if (injectAnnotation.target().kind() == Kind.FIELD) {
                FieldInfo field = injectAnnotation.target().asField();
                if (serviceInterfaces.contains(field.type().name()) && field.annotations().size() == 1) {
                    // e.g. @Inject Greeter
                    throw new IllegalStateException("A gRPC service injection is missing the @GrpcClient qualifier: "
                            + field.declaringClass().name() + "#" + field.name());
                }
            } else if (injectAnnotation.target().kind() == Kind.METHOD) {
                // CDI initializer
                MethodInfo method = injectAnnotation.target().asMethod();
                short position = 0;
                for (Type param : method.parameterTypes()) {
                    position++;
                    if (serviceInterfaces.contains(param.name())) {
                        // e.g. @Inject void setGreeter(Greeter greeter)
                        Set<AnnotationInstance> annotations = new HashSet<>();
                        for (AnnotationInstance annotation : method.annotations()) {
                            if (annotation.target().kind() == Kind.METHOD_PARAMETER
                                    && annotation.target().asMethodParameter().position() == position) {
                                annotations.add(annotation);
                            }
                        }
                        if (annotations.size() > 1) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add the @GrpcClient qualifier: @Inject @GrpcClient("hello-service") Greeter greeter;
  2. If using the generated Mutiny bean, still add @GrpcClient to name/qualify the client
  3. Check all @Inject fields typed as .proto service interfaces

Example fix

// before
@Inject Greeter greeter;

// after
@Inject @GrpcClient("hello-service") Greeter greeter;
Defensive patterns

Strategy: validation

Validate before calling

// every gRPC service injection needs the qualifier
@Inject @GrpcClient("hello-service") Greeter greeter; // correct pattern to copy

Prevention

When it happens

Trigger: A field whose type is a known gRPC service interface has exactly one annotation (@Inject) and no @GrpcClient, e.g. @Inject Greeter greeter; during validateInjectedServiceInterfaces.

Common situations: Following generic CDI examples that omit qualifiers; migrating from other gRPC frameworks; IDE auto-completing @Inject only; removing @GrpcClient during cleanup.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/d3dea496bf57dfb6. Report an issue: GitHub.