{"record":{"id":"d19b73fb38421747","repo":"getsops/sops","slug":"found-key-q-in-encrypted-data-which-starts-with","errorCode":null,"errorMessage":"Found key %q in encrypted data, which starts with the reserved key prefix %q for SOPS metadata","messagePattern":"Found key %q in encrypted data, which starts with the reserved key prefix %q for SOPS metadata","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"stores/metadata.go","lineNumber":309,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n\tif opts.Flatten != MetadataFlattenFull {\n\t\tmd = sops.TreeBranch{\n\t\t\tsops.TreeItem{\n\t\t\t\tKey:   SopsMetadataKey,\n\t\t\t\tValue: md,\n\t\t\t},\n\t\t}\n\t}\n\tvar result sops.TreeBranches\n\tfor _, branch := range data.Branches {\n\t\tnewBranch := make(sops.TreeBranch, 0, len(branch)+len(md))\n\t\tfor _, item := range branch {\n\t\t\tif key, ok := item.Key.(string); ok {\n\t\t\t\tif opts.Flatten == MetadataFlattenFull {\n\t\t\t\t\tif strings.HasPrefix(key, SopsPrefix) {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"Found key %q in encrypted data, which starts with the reserved key prefix %q for SOPS metadata\", key, SopsPrefix)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif key == SopsMetadataKey {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"Found key %q in encrypted data, which is a reserved key used for SOPS metadata\", key)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnewBranch = append(newBranch, item)\n\t\t}\n\t\tfor _, item := range md {\n\t\t\tnewBranch = append(newBranch, item)\n\t\t}\n\t\tresult = append(result, newBranch)\n\t}\n\treturn result, nil\n}\n","sourceCodeStart":291,"sourceCodeEnd":326,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/stores/metadata.go#L291-L326","documentation":"Raised by SerializeMetadata when user data contains a key that begins with the reserved `sops_` prefix while MetadataFlattenFull is active (flat metadata shares the same namespace as data keys). Emitting such a file would make metadata keys indistinguishable from data keys, so sops refuses.","triggerScenarios":"Calling SerializeMetadata (or EmitEncryptedFile with an env/dotenv store) on a tree whose branches contain a string key starting with `sops_`, e.g. `sops_config`, `sops_env_var`, when Flatten is MetadataFlattenFull.","commonSituations":"Env/dotenv files containing variables literally named `SOPS_...` (common in CI configs referencing SOPS_* environment variables) being encrypted with the env store, or scripts generating keys prefixed with sops_.","solutions":["Rename the data key so it does not start with `sops_` (or `SOPS_` in env files)","Store the value under a different name, e.g. `cfg_sops_settings` instead of `sops_settings`","If the key must keep its name, use a format that stores metadata in a nested `sops` mapping (json/yaml stores) instead of flattening","Filter out reserved-prefix keys before encrypting if they are not needed in the encrypted output"],"exampleFix":"// before: env file\nSOPS_CONFIG_URL=https://example.com\n// after: avoid reserved sops_ prefix in flattened stores\nMYAPP_SOPS_CONFIG_URL=https://example.com","handlingStrategy":"validation","validationCode":"func hasReservedKeys(tree sops.Tree, prefix string) []string {\n\tvar bad []string\n\tfor _, branch := range tree.Branches {\n\t\tfor _, item := range branch {\n\t\t\tif k, ok := item.Key.(string); ok && strings.HasPrefix(k, prefix) {\n\t\t\t\tbad = append(bad, k)\n\t\t\t}\n\t\t}\n\t}\n\treturn bad\n}\nif bad := hasReservedKeys(tree, \"sops_\"); len(bad) > 0 {\n\treturn fmt.Errorf(\"rename reserved-prefixed keys before encrypting: %v\", bad)\n}","typeGuard":"func isReservedKey(k interface{}, prefix string) bool {\n\ts, ok := k.(string)\n\treturn ok && strings.HasPrefix(s, prefix)\n}","tryCatchPattern":"out, err := stores.SerializeMetadata(tree, opts)\nif err != nil {\n\tif strings.Contains(err.Error(), \"reserved key prefix\") {\n\t\treturn fmt.Errorf(\"rename keys starting with sops_ before encrypting with flattened metadata: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Never name data keys/env vars with the sops_ (SOPS_) prefix in flattened stores","Use json/yaml stores (nested sops metadata) if such key names are unavoidable","Scan input files for reserved prefixes before encryption","Document key-naming rules for teams generating env files consumed by sops"],"tags":["reserved-key","metadata","naming-collision","sops"],"backgroundTag":"reserved-key-prefix-collision","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}