getsops/sops · error

Unexpected key type %T

Error message

Unexpected key type %T

What it means

Raised inside sopsToGoMap while converting a sops tree branch into plain Go maps: a tree item key is neither a sops.Comment nor a string. The JSON/YAML stores only produce string keys, so this signals a tree built or mutated with a non-string key type.

Source

Thrown at stores/metadata.go:50

	// Only used if Flatten is not MetadataFlattenNone.
	// This does provide a double escape for newlines, since the store itself
	// is already expected to take care of them. This is mainly needed for
	// backwards compatibility with the INI store.
	EscapeNewlines bool
}

// SopsPrefix is the prefix for all metadata entry keys.
const SopsPrefix = SopsMetadataKey + "_"

func sopsToGoMap(mapping sops.TreeBranch) (map[string]interface{}, error) {
	result := make(map[string]interface{})
	for _, item := range mapping {
		if _, ok := item.Key.(sops.Comment); ok {
			continue
		}
		key, ok := item.Key.(string)
		if !ok {
			return nil, fmt.Errorf("Unexpected key type %T", item.Key)
		}
		value, err := sopsToGo(item.Value)
		if err != nil {
			return nil, err
		}
		result[key] = value
	}
	return result, nil
}

func sopsToGoSlice(slice []interface{}) ([]interface{}, error) {
	result := make([]interface{}, 0, len(slice))
	for _, item := range slice {
		if _, ok := item.(sops.Comment); ok {
			continue
		}
		value, err := sopsToGo(item)
		if err != nil {

View on GitHub (pinned to 13442bb981)

Solutions

  1. Convert all TreeItem keys to strings before conversion: fmt.Sprint(key) or string coercion
  2. Skip/strip non-string key items from the branch before conversion
  3. Fix the upstream code that inserts non-string keys into the tree

Example fix

// before
branch = append(branch, sops.TreeItem{Key: 42, Value: v})
// after
branch = append(branch, sops.TreeItem{Key: strconv.Itoa(42), Value: v})
Defensive patterns

Strategy: type-guard

Validate before calling

func allStringKeys(branch sops.TreeBranch) bool {
	for _, item := range branch {
		if _, ok := item.Key.(string); !ok {
			return false
		}
	}
	return true
}

Type guard

func isStringKey(k interface{}) bool {
	_, ok := k.(string)
	return ok
}

Try / catch

result, err := sopsToGo(branch)
if err != nil {
	if strings.HasPrefix(err.Error(), "Unexpected key type") {
		return fmt.Errorf("tree built with non-string key: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling sopsToGo (directly or via treeBranchToMetadata during ExtractMetadata) on a branch containing a TreeItem whose Key is, e.g., an int, bool, or custom type instead of string.

Common situations: Custom stores or plugins that insert numeric/typed keys into branches, programmatic tree manipulation (e.g. appending items with int keys), or code ported from other formats where keys aren't strings.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/80f43399c927d7d4. Report an issue: GitHub.