protoc "X is already defined" duplicate symbol in CI
protoc builds a single symbol table across all inputs. "is already defined" means the same fully qualified name was declared twice, most often because one .proto is included through two different -I roots and compiled as two distinct files.
What this error means
protoc fails with "common/types.proto: \"example.User\" is already defined in ..." or "was already defined by ...", pointing at two paths that resolve to the same file.
common/types.proto: "example.common.Address" is already defined in file
"common/types.proto".
common/types.proto: This file is imported twice under different paths.Common causes
The same proto is reachable via two import roots
Overlapping -I directories let one file be resolved as common/types.proto and types.proto, so protoc compiles and defines it twice.
A file is both listed as input and imported
Passing a proto on the command line while another proto imports it under a different relative path duplicates its symbols.
How to fix it
Give each proto exactly one canonical path
- Pick a single import root that every import is relative to.
- Remove overlapping
-Idirectories that let a file resolve two ways. - Re-run protoc so each file compiles once.
# one root only; all imports are relative to it
protoc -I proto --go_out=gen proto/api/v1/user.protoLet buf manage the module roots
buf resolves each file to one canonical path from buf.yaml, eliminating double-import duplicate symbols.
buf buildHow to prevent it
- Keep a single, non-overlapping import root layout.
- Do not pass a proto as input if another proto imports it under a different path.
- Use buf modules so import roots are defined once in buf.yaml.