getsops/sops · error

Error marshaling metadata: %s

Error message

Error marshaling metadata: %s

What it means

EmitEncryptedFile first serializes the tree's sops metadata via stores.SerializeMetadata with MetadataFlattenBelowTop and newline escaping. If serializing the metadata branch fails (e.g. the sops section contains values or shapes the flattener cannot represent, such as key collisions or non-string keys in the sops branch), this error is returned instead of writing the file.

Source

Thrown at stores/ini/store.go:170

// LoadPlainFile loads a plaintext INI file's bytes onto a sops.TreeBranches runtime object
func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
	branches, err := store.treeBranchesFromIni(in)
	if err != nil {
		return branches, fmt.Errorf("Could not unmarshal input data: %s", err)
	}
	return branches, nil
}

// EmitEncryptedFile returns encrypted INI file bytes corresponding to a sops.Tree
// runtime object
func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
	branches, err := stores.SerializeMetadata(in, stores.MetadataOpts{
		Flatten:        stores.MetadataFlattenBelowTop,
		EscapeNewlines: true,
	})
	if err != nil {
		return nil, fmt.Errorf("Error marshaling metadata: %s", err)
	}
	return store.EmitPlainFile(branches)
}

// EmitPlainFile returns the plaintext INI file bytes corresponding to a sops.TreeBranches object
func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
	out, err := store.iniFromTreeBranches(in)
	if err != nil {
		return nil, fmt.Errorf("Error marshaling to INI: %s", err)
	}
	return out, nil
}

func (store Store) encodeValue(v interface{}) ([]byte, error) {
	switch v := v.(type) {
	case sops.TreeBranches:
		return store.encodeTree(v)
	default:

View on GitHub (pinned to 13442bb981)

Solutions

  1. Inspect the wrapped SerializeMetadata error and fix the offending key in the tree's sops metadata branch
  2. Avoid manually editing the sops metadata section; let sops generate it (e.g. via sops.Tree.Metadata and the normal encrypt path)
  3. Ensure all keys added to the sops branch are strings and unique after flattening
  4. Re-encrypt from the plaintext file with the official sops CLI if metadata was corrupted

Example fix

// before: custom key injected into metadata branch
branch = append(branch, sops.TreeItem{Key: 42, Value: "x"})

// after
branch = append(branch, sops.TreeItem{Key: "custom_key", Value: "x"})
Defensive patterns

Strategy: validation

Validate before calling

if tree.Metadata == (generic.Metadata{}) {
	return errors.New("tree has no metadata; cannot emit encrypted file")
}
for _, item := range tree.Branches[0] {
	if k, ok := item.Key.(string); ok && k == "sops" {
		if _, ok := item.Value.(sops.TreeBranch); !ok {
			return errors.New("sops branch has unexpected shape")
		}
	}
}

Try / catch

out, err := store.EmitEncryptedFile(tree)
if err != nil {
	if strings.Contains(err.Error(), "Error marshaling metadata") {
		return fmt.Errorf("fix sops metadata branch before emitting: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling EmitEncryptedFile on a sops.Tree whose Metadata/sops branch cannot be flattened: e.g. a sops metadata branch containing a key collision under MetadataFlattenBelowTop, non-string keys inside the sops section, or a corrupted metadata structure after programmatic modification.

Common situations: Custom tooling that manipulates tree.Metadata and writes it back in an unexpected shape; migrating a file between store formats so metadata keys lost their expected form; bugs in extensions that inject extra keys into the sops section.

Related errors


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