{"record":{"id":"3e63bd7f4161bdf2","repo":"getsops/sops","slug":"invalid-s-key-configuration-expected-string-in-l","errorCode":null,"errorMessage":"invalid %s key configuration: expected string in list, got %T","messagePattern":"invalid (.+?) key configuration: expected string in list, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/config.go","lineNumber":251,"sourceCode":"\t\t\treturn []string{}, nil\n\t\t}\n\t\t// Existing CSV parsing logic\n\t\tkeys := strings.Split(v, \",\")\n\t\tresult := make([]string, 0, len(keys))\n\t\tfor _, key := range keys {\n\t\t\ttrimmed := strings.TrimSpace(key)\n\t\t\tif trimmed != \"\" { // Skip empty strings (fixes trailing comma issue)\n\t\t\t\tresult = append(result, trimmed)\n\t\t\t}\n\t\t}\n\t\treturn result, nil\n\tcase []interface{}:\n\t\tresult := make([]string, len(v))\n\t\tfor i, item := range v {\n\t\t\tif str, ok := item.(string); ok {\n\t\t\t\tresult[i] = str\n\t\t\t} else {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid %s key configuration: expected string in list, got %T\", fieldName, item)\n\t\t\t}\n\t\t}\n\t\treturn result, nil\n\tcase []string:\n\t\treturn v, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid %s key configuration: expected string, []string, or nil, got %T\", fieldName, field)\n\t}\n}\n\nfunc NewStoresConfig() *StoresConfig {\n\tstoresConfig := &StoresConfig{}\n\tstoresConfig.JSON.Indent = -1\n\tstoresConfig.JSONBinary.Indent = -1\n\treturn storesConfig\n}\n\n// Load loads a sops config file into a temporary struct","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/getsops/sops/blob/13442bb98183887d7a9ac09ec8ab0564673a59d8/config/config.go#L233-L269","documentation":"parseKeyField accepts a string, []string, or nil for a key-group field; this error fires when a YAML list element is not a string (e.g. a map or number) while processing %s key configuration. It names the offending element's Go type to help locate the bad entry in the config file.","triggerScenarios":"A config list entry like `age:\n  - {recipient: age1...}` or `- 123` is passed to parseKeyField via GetAgeKeys/GetKMSKeys/GetPGPKeys/etc., where an item is not a plain string.","commonSituations":"Copy-pasting KMS-style structured entries (arn maps) into an age/pgp list, YAML indentation accidentally nesting a mapping inside a string list, quoting mistakes turning entries into numbers or booleans (e.g. unquoted 12345).","solutions":["Make every list entry a plain quoted string (e.g. `- age1abc...`, `- arn:aws:kms:...` as a single string)","Quote entries that YAML would parse as numbers or booleans","Inspect the exact line indicated by the field name and %T in the message to find the non-string element"],"exampleFix":"# before\nage:\n  - recipient: age1abc...   # map, not string\n# after\nage:\n  - \"age1abc...\"             # plain string entry","handlingStrategy":"validation","validationCode":"// validate that all entries under a key field are plain strings\nfunc isStringList(v interface{}) bool {\n\tswitch l := v.(type) {\n\tcase []interface{}:\n\t\tfor _, item := range l { if _, ok := item.(string); !ok { return false } }\n\t\treturn true\n\tcase []string, string, nil:\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":"func asStringList(field interface{}) ([]string, bool) {\n\tswitch v := field.(type) {\n\tcase string: return []string{v}, true\n\tcase []string: return v, true\n\tcase []interface{}:\n\t\tr := make([]string, 0, len(v))\n\t\tfor _, it := range v {\n\t\t\ts, ok := it.(string); if !ok { return nil, false }\n\t\t\tr = append(r, s)\n\t\t}\n\t\treturn r, true\n\t}\n\treturn nil, false\n}","tryCatchPattern":"keys, err := cfg.GetAgeKeys(creationRuleIndex)\nif err != nil {\n\tif strings.Contains(err.Error(), \"expected string in list\") {\n\t\treturn fmt.Errorf(\"fix .sops.yaml: every list entry must be a quoted plain string: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Write key entries as plain quoted strings, never inline maps","Quote values YAML would treat as numbers/booleans","Run a YAML linter over .sops.yaml before committing","Copy key-list syntax from sops documentation examples, not from other tools' configs"],"tags":["configuration","yaml","type-mismatch","sops"],"backgroundTag":"config-type-mismatch","analyzedSha":"13442bb98183887d7a9ac09ec8ab0564673a59d8","analyzedAt":"2026-09-01T03:53:00.447Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}