getsops/sops · error
invalid %s key configuration: expected string, []string, or
Error message
invalid %s key configuration: expected string, []string, or nil, got %T
What it means
parseKeyField's default branch: the field's overall value is neither a string, a []string, nor nil (e.g. a single map or nested list), so key parsing cannot proceed. Unlike error 66 (bad element inside a list), this fires on the whole field having an unsupported type.
Source
Thrown at config/config.go:258
if trimmed != "" { // Skip empty strings (fixes trailing comma issue)
result = append(result, trimmed)
}
}
return result, nil
case []interface{}:
result := make([]string, len(v))
for i, item := range v {
if str, ok := item.(string); ok {
result[i] = str
} else {
return nil, fmt.Errorf("invalid %s key configuration: expected string in list, got %T", fieldName, item)
}
}
return result, nil
case []string:
return v, nil
default:
return nil, fmt.Errorf("invalid %s key configuration: expected string, []string, or nil, got %T", fieldName, field)
}
}
func NewStoresConfig() *StoresConfig {
storesConfig := &StoresConfig{}
storesConfig.JSON.Indent = -1
storesConfig.JSONBinary.Indent = -1
return storesConfig
}
// Load loads a sops config file into a temporary struct
func (f *configFile) load(bytes []byte) error {
err := yaml.Unmarshal(bytes, f)
if err != nil {
return fmt.Errorf("Could not unmarshal config file: %s", err)
}
return nil
}View on GitHub (pinned to 13442bb981)
Solutions
- Set the field to either a single string or a list of strings in .sops.yaml
- For multiple key groups, use the key_groups structure instead of nesting lists on the key field
- Validate the YAML structure with `sops` dry-run or a schema check after editing
Example fix
# before age: key1: age1abc... # map not accepted # after age: - "age1abc..." - "age1def..."
Defensive patterns
Strategy: validation
Validate before calling
// field must be string, []string, or nil
func keyFieldOk(v interface{}) bool {
switch v.(type) {
case string, []string, []interface{}, nil:
// []interface{} still needs element checks (see error 66)
return true
}
return false
} Type guard
func isScalarOrStringList(v interface{}) bool {
if v == nil { return true }
if s, ok := v.(string); ok { return s != "" }
if l, ok := v.([]interface{}); ok { return len(l) > 0 }
return false
} Try / catch
keys, err := cfg.GetPGPKeys(i)
if err != nil && strings.Contains(err.Error(), "expected string, []string, or nil") {
return fmt.Errorf(".sops.yaml field must be a string or list of strings, not a map: %w", err)
} Prevention
- Never put a mapping (key: value) under age/pgp/kms lists in creation_rules
- Use sops' key_groups structure for multi-group setups instead of nesting lists
- Validate .sops.yaml structure with sops or a YAML schema tool after edits
- Keep one key entry per list line as a quoted string
When it happens
Trigger: Config like `age: {key1: val}` (a map where a string or list is expected), or a nested list `[[a, b]]` passed to GetAgeKeys/GetPGPKeys/GetKMSKeys etc.
Common situations: Confusing per-key creation-rule syntax with key-group syntax in .sops.yaml, pasting structured key objects into fields that sops expects as plain strings, wrong YAML indentation creating a mapping instead of a list of strings.
Related errors
- invalid %s key configuration: expected string in list, got %
- Could not unmarshal config file: %s
- invalid %s key configuration: %w
- config file not found
- error loading config: %s
AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01).
Data as JSON: /api/errors/38ab5e43de62968e.
Report an issue: GitHub.