{"record":{"id":"6acfba69be75183f","repo":"grpc-ecosystem/grpc-gateway","slug":"components-s-q-s-redefines-an-entry-with-a-dif","errorCode":null,"errorMessage":"components.%s.%q: %s redefines an entry with a different value","messagePattern":"components\\.(.+?)\\.%q: (.+?) redefines an entry with a different value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openapiv3-merge/internal/merge/merge.go","lineNumber":355,"sourceCode":"\t\t{\"links\", &dst.Links, &src.Links},\n\t\t{\"callbacks\", &dst.Callbacks, &src.Callbacks},\n\t\t{\"pathItems\", &dst.PathItems, &src.PathItems},\n\t}\n\tfor _, p := range pairs {\n\t\tif len(*p.src) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif *p.dst == nil {\n\t\t\t*p.dst = make(map[string]json.RawMessage, len(*p.src))\n\t\t}\n\t\tfor k, v := range *p.src {\n\t\t\tif prev, dup := (*p.dst)[k]; dup {\n\t\t\t\tsame, err := canonicalEqual(prev, v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"components.%s.%s: %w\", p.name, k, err)\n\t\t\t\t}\n\t\t\t\tif !same {\n\t\t\t\t\treturn fmt.Errorf(\"components.%s.%q: %s redefines an entry with a different value\", p.name, k, srcName)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t(*p.dst)[k] = v\n\t\t}\n\t}\n\treturn nil\n}\n\n// mergeTags appends tags from src to out, deduplicating by `name`. Two tag\n// entries sharing a name must declare identical metadata.\nfunc mergeTags(out *document, seen map[string]json.RawMessage, src *document) error {\n\tfor _, raw := range src.Tags {\n\t\tname, err := tagName(raw)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%s: tags: %w\", src.name, err)\n\t\t}\n\t\tif prev, ok := seen[name]; ok {","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/grpc-ecosystem/grpc-gateway/blob/a58a4436a376a4bcc7d8f10c4d4f919a8438bba9/openapiv3-merge/internal/merge/merge.go#L337-L373","documentation":"Raised in mergeComponents when two inputs define the same-named component (e.g. components.schemas.\"example.v1.User\") with canonically different values. The strict merger rejects conflicting redefinitions, naming the component kind, key, and the input file that redefined it.","triggerScenarios":"Calling Merge where two documents declare the same schema/response/parameter/etc. name with different definitions — e.g. two proto files defining the same message name with different fields, so generated schemas differ.","commonSituations":"Name collisions across proto packages after stripping qualifiers, one team updating a shared schema in their copy only, vendored specs redefining common types, or version-skewed generator outputs for the same type.","solutions":["Rename one of the conflicting components (e.g. fully-qualify proto names so they stay unique)","Make both definitions identical if the duplication is unintentional","Move the shared component into a single input that the others reference via $ref","Align the source definitions (proto messages) so generated schemas match"],"exampleFix":"// before (b.json)\n\"schemas\": { \"example.v1.User\": { ... different fields ... } }\n// after (b.json)\n\"schemas\": { \"example.v2.User\": { ... } }","handlingStrategy":"validation","validationCode":"func findDuplicateComponents(inputs []merge.Input) map[string][]string {\n\tseen := map[string][]string{}\n\tfor _, in := range inputs {\n\t\tvar doc struct { Components map[string]map[string]json.RawMessage `json:\"components\"` }\n\t\tif json.Unmarshal(in.Data, &doc) != nil { continue }\n\t\tfor kind, m := range doc.Components {\n\t\t\tfor k := range m { seen[kind+\".\"+k] = append(seen[kind+\".\"+k], in.Name) }\n\t\t}\n\t}\n\tdups := map[string][]string{}\n\tfor k, v := range seen { if len(v) > 1 { dups[k] = v } }\n\treturn dups\n}","typeGuard":null,"tryCatchPattern":"merged, err := merge.Merge(inputs)\nif err != nil {\n\tif strings.Contains(err.Error(), \"components.\") && strings.Contains(err.Error(), \"redefines\") {\n\t\t// resolve the component name collision before retrying\n\t}\n\treturn err\n}","preventionTips":["Use fully-qualified component names (e.g. package.v1.Message) so cross-file collisions cannot happen","Define shared types once in a common input and $ref them elsewhere","Diff duplicate components when a collision is reported; align the sources","Keep proto package naming conventions that guarantee unique message names"],"tags":["openapi","merge-conflict","components"],"backgroundTag":"duplicate-key-conflict","analyzedSha":"a58a4436a376a4bcc7d8f10c4d4f919a8438bba9","analyzedAt":"2026-09-02T10:28:31.537Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}