getsops/sops · error

Error while flattening metadata

Error message

Error while flattening metadata: %w

What it means

Wrapper emitted by SerializeMetadata when flattenTreeBranch fails to flatten the metadata tree branch into flat key=value items (used when MetadataOpts.Flatten is not MetadataFlattenNone, i.e. env/dotenv-style stores). Flattening fails when the metadata branch contains nested structures that cannot be represented as flat keys.

Solutions

  1. Inspect the wrapped flatten error for the offending metadata key
  2. Remove or normalize non-flattenable metadata fields in custom Metadata
  3. Use MetadataFlattenNone with a store that supports nested metadata (json/yaml) instead of env formats
  4. Let sops generate the metadata (via LoadEncryptedFile) rather than hand-building it

Example fix

// before
out, err := stores.SerializeMetadata(tree, stores.MetadataOpts{Flatten: stores.MetadataFlattenFull})
// after: use a format whose metadata doesn't need flattening, or keep none
out, err := stores.SerializeMetadata(tree, stores.MetadataOpts{Flatten: stores.MetadataFlattenNone})
Defensive patterns

Strategy: try-catch

Validate before calling

// only flatten for env-style stores; verify metadata is flat-friendly
func canFlatten(md sops.Metadata) bool {
	m, _ := stores.MetadataFromInternal(md) // must convert cleanly first
	_ = m
	return true // additionally verify no exotic custom fields
}

Try / catch

out, err := stores.SerializeMetadata(tree, opts)
if err != nil {
	if strings.HasPrefix(err.Error(), "Error while flattening metadata") {
		return fmt.Errorf("metadata cannot be flattened for this store; use MetadataFlattenNone with json/yaml store: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling SerializeMetadata with Flatten set to MetadataFlattenPartial or MetadataFlattenFull while the converted metadata branch contains values (nested maps/lists) that flattenTreeBranch cannot flatten — e.g. malformed or unexpectedly deep metadata structures from a hand-built Metadata.

Common situations: Writing dotenv/env-format encrypted files with custom or incomplete metadata, converting between store formats (json → env) where metadata shapes differ, custom metadata fields that flattenTreeBranch rejects.

Related errors


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

Appendix: source

Thrown at stores/metadata.go:281

		return tb, nil
	}
	return nil, fmt.Errorf("Internal error: unexpected metadata conversion result %T", metadata)
}

// SerializeMetadata embeds the metadata of `data` into its tree branches.
func SerializeMetadata(data sops.Tree, opts MetadataOpts) (sops.TreeBranches, error) {
	md, err := metadataToTreeBranch(metadataFromInternal(data.Metadata))
	if err != nil {
		return nil, fmt.Errorf("Error while serializing metadata: %w", err)
	}
	if opts.Flatten != MetadataFlattenNone {
		var prefix string
		if opts.Flatten == MetadataFlattenFull {
			prefix = SopsPrefix
		}
		md, err = flattenTreeBranch(md, prefix)
		if err != nil {
			return nil, fmt.Errorf("Error while flattening metadata: %w", err)
		}
		if opts.EscapeNewlines {
			for i, item := range md {
				if value, ok := item.Value.(string); ok {
					md[i] = sops.TreeItem{
						Key:   item.Key,
						Value: strings.ReplaceAll(value, "\n", "\\n"),
					}
				}
			}
		}
	}
	if opts.Flatten != MetadataFlattenFull {
		md = sops.TreeBranch{
			sops.TreeItem{
				Key:   SopsMetadataKey,
				Value: md,
			},

View on GitHub (pinned to 13442bb981)