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
- Find the duplicate: enable debug logging on io.quarkus.grpc.reflection and inspect registered services; identify which proto produces the duplicate name.
- Ensure each proto service has a unique package (package a.b; in the .proto) so full service names don't collide.
- Remove duplicate service bean registrations — a proto service should map to exactly one implementation bean.
- 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
- One proto service = one implementation bean; don't double-register
- Use distinct proto packages for services with the same name
- Exclude older artifacts shipping the same proto
- Review @GrpcService-annotated beans for accidental duplicates
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
- Couldn't extract all parameters information for constructor
- Failed to set dev services config
- Failed to set dev services override config
- Unable to find or load top command: <className>
- Unable to find the following conversion class: ${customConve
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/2b38d05b5eba2716.
Report an issue: GitHub.