mikefarah/yq · error

TOML encoder expects a mapping at the root level

Error message

TOML encoder expects a mapping at the root level

What it means

TOML documents are tables at the root, so the TOML encoder requires a top-level MappingNode. Scalars are special-cased to print the raw value (for standalone selections), but any other Kind (sequence, alias, etc.) fails with this error.

Source

Thrown at pkg/yqlib/encoder_toml.go:33

	wroteRootAttr bool // Track if we wrote root-level attributes before tables
	prefs         TomlPreferences
}

func NewTomlEncoder() Encoder {
	return NewTomlEncoderWithPrefs(ConfiguredTomlPreferences)
}

func NewTomlEncoderWithPrefs(prefs TomlPreferences) Encoder {
	return &tomlEncoder{prefs: prefs}
}

func (te *tomlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
	if node.Kind != MappingNode {
		// For standalone selections, TOML tests expect raw value for scalars
		if node.Kind == ScalarNode {
			return writeString(writer, node.Value+"\n")
		}
		return fmt.Errorf("TOML encoder expects a mapping at the root level")
	}

	// Encode to a buffer first if colors are enabled
	var buf bytes.Buffer
	var targetWriter io.Writer
	targetWriter = writer
	if te.prefs.ColorsEnabled {
		targetWriter = &buf
	}

	// Encode a root mapping as a sequence of attributes, tables, and arrays of tables
	if err := te.encodeRootMapping(targetWriter, node); err != nil {
		return err
	}

	if te.prefs.ColorsEnabled {
		colourised := te.colorizeToml(buf.Bytes())
		_, err := writer.Write(colourised)

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Wrap the list in a map: `yq -o toml '{items: .}' file.yaml`.
  2. If the source is a top-level array, key it first: `yq -o toml '{"item0": .[0], "item1": .[1]}'` or use to_entries-style transforms.
  3. Keep the default `.` expression if the document root is already a mapping.
  4. Use json/yaml output for array-root data.

Example fix

# before
yq -o toml '.deps' file.yaml   # deps is a list -> error

# after
yq -o toml '{"deps": .deps}' file.yaml   # wait: better -> yq -o toml '.' file.yaml (root map) or wrap: {deps: [...]}
Defensive patterns

Strategy: validation

Validate before calling

[ "$(yq 'kind' file.yaml)" = "mapping" ] || echo "TOML output needs a mapping root"

Type guard

isTomlSafe() { [ "$(yq 'kind' "$1")" = "mapping" ]; }

Try / catch

yq -o toml '.' file.yaml || yq -o toml '{items: .}' file.yaml

Prevention

When it happens

Trigger: `yq -o toml '.someArray' file.yaml` where the expression yields a sequence/alias root; piping a JSON array into TOML output; selecting a list as the whole document.

Common situations: Converting YAML/JSON lists (e.g. dependency arrays, CI step lists) to TOML; filters like `.[]` or `map(...)` yielding sequences; expecting TOML to represent a top-level array like JSON does.

Related errors


AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05). Data as JSON: /api/errors/8cd09b0ce713a67f. Report an issue: GitHub.