mikefarah/yq · error

cannot encode %v to XML - only maps can be encoded

Error message

cannot encode %v to XML - only maps can be encoded

What it means

The XML encoder's top-level Encode only supports mapping nodes (and bare scalars as character data); anything else — a top-level sequence, alias, or other kind — is rejected with this message. XML documents need a root element, which only a map can provide.

Source

Thrown at pkg/yqlib/encoder_xml.go:95

			return err
		}
	}

	switch node.Kind {
	case MappingNode:
		err := e.encodeTopLevelMap(encoder, node)
		if err != nil {
			return err
		}
	case ScalarNode:
		var charData xml.CharData = []byte(node.Value)
		err := encoder.EncodeToken(charData)
		if err != nil {
			return err
		}
		return encoder.Flush()
	default:
		return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", node.Tag)
	}

	return encoder.EncodeToken(newLine)

}

func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode) error {
	err := e.encodeComment(encoder, headAndLineComment(node))
	if err != nil {
		return err
	}
	for i := 0; i < len(node.Content); i += 2 {
		key := node.Content[i]
		value := node.Content[i+1]

		start := xml.StartElement{Name: xml.Name{Local: key.Value}}
		log.Debugf("comments of key %v", key.Value)
		err := e.encodeComment(encoder, headAndLineComment(key))

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Wrap the array in a map, e.g. `yq -o xml '{items: .}'` so there is a root element.
  2. Select a specific map from the sequence: `yq -o xml '.[0]'`.
  3. Use an expression that returns a single object rather than all(...)/[...] results.
  4. If lists are expected, restructure the source data so the root is an object with an array field.

Example fix

// before
yq -o xml '.' list.yaml        # root is an array
// after
yq -o xml '{items: .}' list.yaml
Defensive patterns

Strategy: validation

Validate before calling

yq 'kind' file.yaml  # must be "map" (or "scalar") for -o xml

Type guard

// shell
[ "$(yq 'kind' doc.yaml)" = "map" ] || yq -o xml '{root: .}' doc.yaml

Try / catch

// Go
if err := xmlEnc.Encode(w, node); err != nil {
    if strings.Contains(err.Error(), "only maps can be encoded") {
        // wrap sequence in a map: {items: node} and retry
    }
}

Prevention

When it happens

Trigger: Running `yq -o xml '.' file.yaml` where the root document is an array (e.g. `- a\n- b`) or an alias node instead of a map.

Common situations: Converting YAML/JSON arrays (lists of records) directly to XML; output of a select/all() expression that returns a sequence; XML round-trips where the document root was an array of repeated elements.

Related errors


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