getsops/sops · error

Internal error: cannot find root

Error message

Internal error: cannot find root

What it means

unflattenTreeBranch asserts that the reconstructed root of the nested tree is a sops.TreeBranch (a map). This is a defensive internal invariant check: if convert() returned something that is not a TreeBranch, the flattening logic produced an unexpected shape and the function cannot return a valid TreeBranch.

Source

Thrown at stores/flatten.go:199

		}
		if key, ok := item.Key.(string); ok {
			tokens := tokenize(key)
			err := place(&item.Value, tokens, root)
			if err != nil {
				return nil, fmt.Errorf("Error while unflattening %q: %w", key, err)
			}
		} else {
			return nil, fmt.Errorf("Found non-string key %q when unflattening", item.Key)
		}
	}
	result, err := convert(root)
	if err != nil {
		return nil, fmt.Errorf("Error while unflattening: %w", err)
	}
	if tb, ok := result.(sops.TreeBranch); ok {
		return tb, nil
	}
	return nil, fmt.Errorf("Internal error: cannot find root")
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Flatten

func flattenDescendValue(value interface{}, key string, destination sops.TreeBranch, destinationMap *map[string]bool) (sops.TreeBranch, error) {
	switch value := value.(type) {
	case sops.TreeBranch:
		return flattenDescendMap(value, key+mapSeparator, destination, destinationMap)
	case []interface{}:
		return flattenDescendArray(value, key+listSeparator, destination, destinationMap)
	}
	if _, ok := (*destinationMap)[key]; ok {
		return nil, fmt.Errorf("Found key collision %q while flattening", key)
	}
	destination = append(destination, sops.TreeItem{
		Key:   key,
		Value: value,

View on GitHub (pinned to 13442bb981)

Solutions

  1. Report/fix as a bug: inspect whether convert() returned a []interface{} (list-only root) or scalar and correct the node construction
  2. Check that at least one mapToken path exists in the flattened keys so the root builds subkeys
  3. Verify you are on an unmodified, released version of github.com/getsops/sops/v3/stores
Defensive patterns

Strategy: try-catch

Type guard

if tb, ok := result.(sops.TreeBranch); ok {
	// safe to use tb
}

Try / catch

tb, err := unflattenTreeBranch(branch)
if err != nil {
	if err.Error() == "Internal error: cannot find root" {
		return fmt.Errorf("internal sops bug, please report: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Practically unreachable in normal use because convert() returns sops.TreeBranch for a root with subkeys and TreeBranch{} for an empty root; it can only surface if convert's internal logic changes or a nil/degenerate node tree reaches the type assertion, i.e. a genuine bug in the stores package.

Common situations: Seen only when hacking on sops itself — modifying convert() or place() so the root node ends up holding only a scalar value or only list indices — or when bisecting an unexpected regression in the flatten/unflatten code.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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