quarkusio/quarkus · error · IllegalStateException

Service already defined: ${fullyQualifiedServiceName}

Error message

Service already defined: ${fullyQualifiedServiceName}

What it means

During reflection index building, every service's fully qualified name (package.Service) must be unique across all FileDescriptors. processService throws this IllegalStateException if the symbol map already contains that fully qualified service name.

Source

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

            throw new IllegalStateException("File name already used: " + name);
        }
        descriptorsByName.put(name, fd);
        for (Descriptors.ServiceDescriptor service : fd.getServices()) {
            processService(service, fd, descriptorsBySymbol);
        }
        for (Descriptors.Descriptor type : fd.getMessageTypes()) {
            processType(type, fd, descriptorsBySymbol, descriptorsByExtensionAndNumber);
        }
        for (Descriptors.FieldDescriptor extension : fd.getExtensions()) {
            processExtension(extension, fd, descriptorsByExtensionAndNumber);
        }
    }

    private void processService(Descriptors.ServiceDescriptor service, FileDescriptor fd,
            Map<String, FileDescriptor> descriptorsBySymbol) {
        String fullyQualifiedServiceName = service.getFullName();
        if (descriptorsBySymbol.containsKey(fullyQualifiedServiceName)) {
            throw new IllegalStateException("Service already defined: " + fullyQualifiedServiceName);
        }
        descriptorsBySymbol.put(fullyQualifiedServiceName, fd);
        for (Descriptors.MethodDescriptor method : service.getMethods()) {
            String fullyQualifiedMethodName = method.getFullName();
            if (descriptorsBySymbol.containsKey(fullyQualifiedMethodName)) {
                throw new IllegalStateException(
                        "Method already defined: " + fullyQualifiedMethodName + " in " + fullyQualifiedServiceName);
            }
            descriptorsBySymbol.put(fullyQualifiedMethodName, fd);
        }
    }

    private void processType(Descriptors.Descriptor type, FileDescriptor fd,
            Map<String, FileDescriptor> descriptorsBySymbol,
            Map<String, Map<Integer, FileDescriptor>> descriptorsByExtensionAndNumber) {
        String fullyQualifiedTypeName = type.getFullName();
        if (descriptorsBySymbol.containsKey(fullyQualifiedTypeName)) {
            throw new IllegalStateException("Type already defined: " + fullyQualifiedTypeName);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make service full names unique by adjusting the proto 'package' declaration or the service name in the duplicate file.
  2. Delete the duplicated proto copy from your sources or dependencies.
  3. If generated twice by the build, fix duplicate proto source directories in the build config so each proto compiles once.
  4. Verify with a listing of descriptor names before server startup (add a breakpoint/logging in GrpcServerIndex during debugging).

Example fix

// before: fileA.proto and fileB.proto both contain
package my.app;
service Greeter {...}
// after: fileB.proto
package my.app.v2;
service Greeter {...}
Defensive patterns

Strategy: validation

Validate before calling

// proto lint: collect all service full names and assert uniqueness
Set<String> seen = new HashSet<>();
for (ProtoFile f : allProtos) {
  for (ServiceDef s : f.getServices()) {
    if (!seen.add(f.getPackage() + "." + s.getName()))
      throw new IllegalStateException("Duplicate service full name");
  }
}

Try / catch

try {
    startServer();
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Service already defined:")) {
        // fix the proto package/name collision reported in the message
    } else throw e;
}

Prevention

When it happens

Trigger: Two different proto files declare services with the same package+name; a service name collides with an already-recorded symbol from another descriptor processed earlier by processFileDescriptor.

Common situations: Copy-pasting a proto into another file without changing the package; importing a third-party proto that redeclares a service with the same full name; code-generating the same proto twice under different file names.

Related errors


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