{"record":{"id":"894d14607e68185d","repo":"getsops/sops","slug":"found-key-collision-q-while-flattening","errorCode":null,"errorMessage":"Found key collision %q while flattening","messagePattern":"Found key collision %q while flattening","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"stores/flatten.go","lineNumber":213,"sourceCode":"\t}\n\tif tb, ok := result.(sops.TreeBranch); ok {\n\t\treturn tb, nil\n\t}\n\treturn nil, fmt.Errorf(\"Internal error: cannot find root\")\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Flatten\n\nfunc flattenDescendValue(value interface{}, key string, destination sops.TreeBranch, destinationMap *map[string]bool) (sops.TreeBranch, error) {\n\tswitch value := value.(type) {\n\tcase sops.TreeBranch:\n\t\treturn flattenDescendMap(value, key+mapSeparator, destination, destinationMap)\n\tcase []interface{}:\n\t\treturn flattenDescendArray(value, key+listSeparator, destination, destinationMap)\n\t}\n\tif _, ok := (*destinationMap)[key]; ok {\n\t\treturn nil, fmt.Errorf(\"Found key collision %q while flattening\", key)\n\t}\n\tdestination = append(destination, sops.TreeItem{\n\t\tKey:   key,\n\t\tValue: value,\n\t})\n\t(*destinationMap)[key] = true\n\treturn destination, nil\n}\n\nfunc flattenDescendMap(branch sops.TreeBranch, prefix string, destination sops.TreeBranch, destinationMap *map[string]bool) (sops.TreeBranch, error) {\n\tfor _, item := range branch {\n\t\tif _, ok := item.Key.(sops.Comment); ok {\n\t\t\tcontinue\n\t\t}\n\t\tif key, ok := item.Key.(string); ok {\n\t\t\tvar err error\n\t\t\tdestination, err = flattenDescendValue(item.Value, prefix+key, destination, destinationMap)\n\t\t\tif err != nil {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/stores/flatten.go#L195-L231","documentation":"While flattening, every leaf value gets a unique joined path key (e.g. \"sops__map_metadata\"). flattenDescendValue checks destinationMap before inserting a leaf; if the same path key was already written, this error fires because two different values would silently overwrite each other in the flat map.","triggerScenarios":"Flattening a TreeBranch that contains two entries resolving to the same flattened path — e.g. a map key \"a\" with scalar value AND a deeper branch whose joined path produces the identical key, or duplicate keys at the same level such as {\"a\": 1, \"a\": 2} in the branch.","commonSituations":"INI-adjacent workflows where keys with dots or the literal separators __map_ / __list_ in user data collide with generated separator paths; programmatic tree construction that appended the same key twice; parsing formats that allow duplicate keys (e.g. INI with AllowNonUniqueSections) then flattening for metadata serialization.","solutions":["Find and remove/rename the duplicate key in the source tree so each flattened path is unique","Avoid using the literal substrings __map_ and __list_ in your configuration keys, or rename one of the colliding keys","Deduplicate branches before calling flatten (e.g. build a set of keys and reject duplicates at load time)"],"exampleFix":"// before\nbranch := sops.TreeBranch{\n  {Key: \"a\", Value: \"x\"},\n  {Key: \"a\", Value: \"y\"}, // duplicate -> collision\n}\n\n// after\nbranch := sops.TreeBranch{\n  {Key: \"a\", Value: \"x\"},\n  {Key: \"a2\", Value: \"y\"},\n}","handlingStrategy":"validation","validationCode":"keys := map[string]int{}\nfor _, item := range branch {\n\tk := fmt.Sprintf(\"%v\", item.Key)\n\tkeys[k]++\n\tif keys[k] > 1 {\n\t\treturn fmt.Errorf(\"duplicate key %q in branch\", k)\n\t}\n}","typeGuard":null,"tryCatchPattern":"flat, err := flattenTreeBranch(branch, \"\")\nif err != nil {\n\tvar coll string\n\tif n, _ := fmt.Sscanf(err.Error(), \"Found key collision %q\", &coll); n == 1 {\n\t\treturn fmt.Errorf(\"rename colliding key %s\", coll)\n\t}\n\treturn err\n}","preventionTips":["Never include __map_ or __list_ literals in your config keys","Reject duplicate keys when loading documents","Deduplicate programmatically-built branches before flattening"],"tags":["go","sops","key-collision","flatten"],"backgroundTag":"duplicate-key-collision","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}