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
- Make service full names unique by adjusting the proto 'package' declaration or the service name in the duplicate file.
- Delete the duplicated proto copy from your sources or dependencies.
- If generated twice by the build, fix duplicate proto source directories in the build config so each proto compiles once.
- 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
- Give each proto file a distinct package
- Lint protos for duplicate fully-qualified service names in CI
- Don't copy protos between files without renaming the package
- Compile each proto exactly once (check source dir config)
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
- Extension name ${extensionName} and number ${extensionNumber
- File name already used: ${name}
- Method already defined: ${fullyQualifiedMethodName} in ${ful
- Type already defined: ${fullyQualifiedTypeName}
- Code generation failed. Please check the log above for detai
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/6ac1f4ff3d2ec22f.
Report an issue: GitHub.