mikefarah/yq · error

unsupported type %v

Error message

unsupported type %v

What it means

doEncode dispatches on node Kind (mapping, sequence, scalar) and has no case for anything else — an AliasNode or other kind reaching it fails with `unsupported type %v` reporting the node tag. It means an alias (or non-standard node) is nested inside a map/array being XML-encoded.

Source

Thrown at pkg/yqlib/encoder_xml.go:201

	case ScalarNode:
		err := e.encodeStart(encoder, node, start)
		if err != nil {
			return err
		}

		var charData xml.CharData = []byte(node.Value)
		err = encoder.EncodeToken(charData)
		if err != nil {
			return err
		}

		if err = e.encodeComment(encoder, lineComment(node)); err != nil {
			return err
		}

		return e.encodeEnd(encoder, node, start)
	}
	return fmt.Errorf("unsupported type %v", node.Tag)
}

var xmlEncodeMultilineCommentRegex = regexp.MustCompile(`(^|\n) *# ?(.*)`)
var xmlEncodeSingleLineCommentRegex = regexp.MustCompile(`^\s*#(.*)\n?`)
var chompRegexp = regexp.MustCompile(`\n$`)

func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) error {
	if commentStr != "" {
		log.Debugf("got comment [%v]", commentStr)
		// multi line string
		if len(commentStr) > 2 && strings.Contains(commentStr[1:len(commentStr)-1], "\n") {
			commentStr = chompRegexp.ReplaceAllString(commentStr, "")
			log.Debugf("chompRegexp [%v]", commentStr)
			commentStr = xmlEncodeMultilineCommentRegex.ReplaceAllString(commentStr, "$1$2")
			log.Debugf("processed multiline [%v]", commentStr)
			// if the first line is non blank, add a space
			if commentStr[0] != '\n' && commentStr[0] != ' ' {
				commentStr = " " + commentStr

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Dereference aliases first: yq -o json in.yaml | yq -o xml, or use an expression that materializes values.
  2. Inline the anchored value instead of using an alias in the source.
  3. Normalize the tree before encoding in embedded usage (resolve alias nodes to their targets).
  4. Patch doEncode to add an AliasNode case delegating to the alias target.

Example fix

// before
base: &b {x: 1}
derived: *b
// after
base: &b {x: 1}
derived: {x: 1}
Defensive patterns

Strategy: type-guard

Validate before calling

yq '[.. | select(kind == "alias")] | length' in.yaml  # must be 0 for -o xml

Type guard

// Go
func hasAliasDeep(n *yqlib.CandidateNode) bool {
    if n.Kind == yqlib.AliasNode { return true }
    for _, c := range n.Content { if hasAliasDeep(c) { return true } }
    return false
}

Try / catch

// Go
if err := enc.Encode(w, node); err != nil {
    if strings.Contains(err.Error(), "unsupported type") {
        node = dereferenceAliases(node) // JSON round-trip
    }
}

Prevention

When it happens

Trigger: Encoding to XML a document where a value inside a map or array is an unresolved AliasNode (kind AliasNode), e.g. `a: &x 1\nb: *x` encoded without the alias being resolved by evaluation.

Common situations: YAML with anchors converted straight to XML; alias-bearing documents whose aliases were not dereferenced because the expression did not touch them; embedding yqlib with hand-built trees.

Related errors


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