mikefarah/yq · error

INI encoder supports only MappingNode at the root level, got

Error message

INI encoder supports only MappingNode at the root level, got %v

What it means

The INI encoder can only serialize a top-level MappingNode, because INI files are inherently key/value sections. If the root CandidateNode is a scalar, sequence, or alias, Encode returns this error instead of guessing a representation.

Source

Thrown at pkg/yqlib/encoder_ini.go:94

				// Process nested key-value pairs.
				for j := 0; j < len(valueNode.Content); j += 2 {
					nestedKeyNode := valueNode.Content[j]
					nestedValueNode := valueNode.Content[j+1]
					if nestedValueNode.Kind == ScalarNode {
						_, err := section.NewKey(nestedKeyNode.Value, nestedValueNode.Value)
						if err != nil {
							return err
						}
					} else {
						log.Debugf("Skipping nested non-scalar value for key %s: %v", nestedKeyNode.Value, nestedValueNode.Kind)
					}
				}
			default:
				log.Debugf("Skipping non-scalar value for key %s: %v", key, valueNode.Kind)
			}
		}
	} else {
		return fmt.Errorf("INI encoder supports only MappingNode at the root level, got %v", node.Kind)
	}

	// Use a buffer to store the INI output as the library doesn't support direct io.Writer with indent.
	var buffer bytes.Buffer
	_, err := cfg.WriteToIndent(&buffer, ie.indentString)
	if err != nil {
		return err
	}

	// Write the buffer content to the provided writer.
	_, err = writer.Write(buffer.Bytes())
	return err
}

// writeStringINI is a helper function to write a string to the provided writer for INI encoder.
func writeStringINI(writer io.Writer, content string) error {
	_, err := writer.Write([]byte(content))
	return err

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Ensure the expression evaluates to a mapping, e.g. wrap results in `{...}`: `yq -o ini '{"root": .}'`.
  2. If the value is a sequence, convert it to a map first (e.g. with with_entries or to_entries style transforms) before encoding.
  3. Choose a format that supports arrays/scalars at root (json/yaml) if the data is not map-shaped.
  4. If a selection yields a scalar, drop the filter or re-shape the document before `-o ini`.

Example fix

# before
yq -o ini '.items' config.yaml   # items is an array -> error

# after
yq -o ini '{"items": {"count": (.items | length)}}' config.yaml
Defensive patterns

Strategy: validation

Validate before calling

kind=$(yq 'kind' file.yaml)
[ "$kind" = "mapping" ] || { echo "INI output requires a map root; got $kind" >&2; exit 1; }

Type guard

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

Try / catch

out=$(yq -o ini '.' file.yaml 2>&1) || { echo "INI encode failed: $out"; exit 1; }

Prevention

When it happens

Trigger: Calling yq with `-o ini` (or Format INI) on input whose evaluated root is not a map — e.g. `yq -o ini '.a' file.yaml` returning a scalar, or a JSON array piped to INI output.

Common situations: Converting JSON arrays to INI; piping a scalar expression result to `-o ini`; selecting a nested section then encoding it as the whole document; forgetting that a filter may yield a sequence.

Related errors


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