quarkusio/quarkus · error · IllegalStateException

The original implementation class of a gRPC service not foun

Error message

The original implementation class of a gRPC service not found: ${originalImplName}

What it means

During Quarkus gRPC Dev UI processing, the build index is searched for the original (non-Mutiny) generated gRPC base class that corresponds to each Mutiny-generated service class. The Mutiny class name (e.g. examples.MutinyGreeterGrpc) is transformed by stripping the 'Mutiny' prefix, and the resulting class must exist in the Jandex index. If it does not, the deployment build fails with this IllegalStateException.

Source

Thrown at extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/devui/GrpcDevUIProcessor.java:245

        return null;
    }

    @BuildStep(onlyIf = IsLocalDevelopment.class)
    JsonRPCProvidersBuildItem createJsonRPCServiceForCache() {
        return new JsonRPCProvidersBuildItem(GrpcJsonRPCService.class);
    }

    private Collection<Class<?>> getGrpcServices(IndexView index) throws ClassNotFoundException {
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        Set<String> serviceClassNames = new HashSet<>();
        for (ClassInfo mutinyGrpc : index.getAllKnownImplementors(GrpcDotNames.MUTINY_GRPC)) {
            // Find the original impl class
            // e.g. examples.MutinyGreeterGrpc -> examples.GreeterGrpc
            DotName originalImplName = DotName
                    .createSimple(mutinyGrpc.name().toString().replace(MutinyGrpcGenerator.CLASS_PREFIX, ""));
            ClassInfo originalImpl = index.getClassByName(originalImplName);
            if (originalImpl == null) {
                throw new IllegalStateException(
                        "The original implementation class of a gRPC service not found:" + originalImplName);
            }
            // Must declare static io.grpc.ServiceDescriptor getServiceDescriptor()
            MethodInfo getServiceDescriptor = originalImpl.method("getServiceDescriptor");
            if (getServiceDescriptor != null && Modifier.isStatic(getServiceDescriptor.flags())
                    && getServiceDescriptor.returnType().name().toString().equals(ServiceDescriptor.class.getName())) {
                serviceClassNames.add(getServiceDescriptor.declaringClass().name().toString());
            }
        }

        serviceClassNames.add(HealthGrpc.class.getName());
        DevConsoleManager.setGlobal("io.quarkus.grpc.serviceClassNames", serviceClassNames);

        List<Class<?>> serviceClasses = new ArrayList<>();
        for (String className : serviceClassNames) {
            serviceClasses.add(tccl.loadClass(className));
        }
        return serviceClasses;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the base (non-Mutiny) gRPC service classes are generated: keep the default quarkus.generate-code.grpc settings so both <Name>Grpc and Mutiny<Name>Grpc are produced.
  2. If stubs are pre-generated and committed, make sure the base *Grpc classes are on the application classpath (not just the Mutiny ones) so Jandex can index them.
  3. Check that generated sources are included in indexing (they normally are inside the same module); avoid exclude patterns in quarkus.index-dependency or jandex config that drop the generated package.
  4. Rebuild cleanly (mvn clean install) so code generation re-runs and both classes are regenerated consistently.

Example fix

// before (pom.xml disables base class generation)
<plugin>org.xolstice.maven.plugins:protobuf-maven-plugin ... only mutiny generation</plugin>
// after
Remove custom exclusions and let quarkus-maven-plugin generate both:
<Name>Grpc.java and Mutiny<Name>Grpc.java in the same package
Defensive patterns

Strategy: validation

Validate before calling

// in a deployment test or startup check
DotName impl = DotName.createSimple(mutinyName.replace("Mutiny", ""));
if (index.getClassByName(impl) == null) {
    throw new IllegalStateException("Missing generated base class: " + impl + "; check gRPC code-gen config");
}

Try / catch

try {
    processServices();
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("The original implementation class of a gRPC service not found")) {
        // fix code-gen config or add missing generated sources, then rebuild
    } else throw e;
}

Prevention

When it happens

Trigger: A proto file produces Mutiny<Name>Grpc classes but the base <Name>Grpc class is missing from the index — e.g. quarkus-grpc code-gen is configured with generate-code non-mutiny disabled, the base generated class was excluded from indexing, or a custom protoc plugin setup generates only the Mutiny variant.

Common situations: Custom gRPC code generation configs that disable base class generation; mixing pre-generated stubs (only Mutiny classes committed) with Quarkus indexing; upgrading Quarkus and changing quarkus.generate-code.grpc options.

Related errors


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