quarkusio/quarkus · error · IllegalStateException

Duplicated gRPC service: ${serviceName}

Error message

Duplicated gRPC service: ${serviceName}

What it means

When building the reflection index of all gRPC services served by the server, each ServiceDescriptor's name must be unique. If two service descriptors share the same service name, GrpcServerIndex's constructor throws this IllegalStateException instead of building an ambiguous reflection index.

Source

Thrown at extensions/grpc/reflection/src/main/java/io/quarkus/grpc/reflection/service/GrpcServerIndex.java:49

            List<ServerServiceDefinition> definitions) {
        Queue<FileDescriptor> fileDescriptorsToProcess = new ArrayDeque<>();
        Set<String> files = new HashSet<>();
        Set<String> names = new HashSet<>();
        Set<FileDescriptor> services = new HashSet<>();
        Map<String, FileDescriptor> descriptorsByName = new LinkedHashMap<>();
        Map<String, FileDescriptor> descriptorsBySymbol = new LinkedHashMap<>();
        Map<String, Map<Integer, FileDescriptor>> descriptorsByExtensionAndNumber = new LinkedHashMap<>();

        // Collect the services
        for (ServerServiceDefinition definition : definitions) {
            ServiceDescriptor serviceDescriptor = definition.getServiceDescriptor();
            if (serviceDescriptor.getSchemaDescriptor() instanceof ProtoFileDescriptorSupplier) {
                ProtoFileDescriptorSupplier supplier = (ProtoFileDescriptorSupplier) serviceDescriptor
                        .getSchemaDescriptor();
                FileDescriptor fd = supplier.getFileDescriptor();
                String serviceName = serviceDescriptor.getName();
                if (names.contains(serviceName)) {
                    throw new IllegalStateException("Duplicated gRPC service: " + serviceName);
                }
                services.add(fd);
                names.add(serviceName);

                if (!files.contains(fd.getName())) {
                    files.add(fd.getName());
                    fileDescriptorsToProcess.add(fd);
                }
            }
        }

        // Traverse the set of service and add dependencies
        while (!fileDescriptorsToProcess.isEmpty()) {
            FileDescriptor fd = fileDescriptorsToProcess.remove();
            processFileDescriptor(fd, descriptorsByName, descriptorsBySymbol, descriptorsByExtensionAndNumber);
            for (FileDescriptor dep : fd.getDependencies()) {
                if (!files.contains(dep.getName())) {
                    files.add(dep.getName());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Find the duplicate: enable debug logging on io.quarkus.grpc.reflection and inspect registered services; identify which proto produces the duplicate name.
  2. Ensure each proto service has a unique package (package a.b; in the .proto) so full service names don't collide.
  3. Remove duplicate service bean registrations — a proto service should map to exactly one implementation bean.
  4. If two versions of the same proto are on the classpath (e.g. via a transitive dependency), exclude the older artifact.

Example fix

// before: two protos both declaring
package foo;
service Greeter {...}
// after
package foo.v1;
service Greeter {...}   // unique full name foo.v1.Greeter
Defensive patterns

Strategy: try-catch

Type guard

boolean hasDuplicate(List<String> names) {
  return names.size() != new HashSet<>(names).size();
}

Try / catch

try {
    startServer();
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Duplicated gRPC service:")) {
        // inspect service bean registration and proto packages for the duplicated name
    } else throw e;
}

Prevention

When it happens

Trigger: Registering two gRPC services (or the same service implementation twice, e.g. two beans exposed as the same proto service, or a service registered both directly and via a different port/bean) so io.grpc.ServerServiceDefinition entries contain a duplicated service name.

Common situations: Declaring the same service bean twice (e.g. @GrpcService plus manual registration); two different proto packages compiled to the same service full name; accidentally shipping the same proto twice under different files; running reflection against a server with duplicated service registrations from two versions of the same proto.

Related errors


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