mikefarah/yq · error
cannot use %v as attribute, only scalars are supported
Error message
cannot use %v as attribute, only scalars are supported
What it means
XML attributes (keys starting with the attribute prefix, default `+` or `@a`) must be scalar values because XML attributes can only hold text. If a key like `+attr` maps to a map/sequence, encodeMap rejects it with this message naming the offending tag.
Source
Thrown at pkg/yqlib/encoder_xml.go:276
name != e.prefs.ContentName &&
name != e.prefs.DirectiveName &&
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
}
func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
log.Debug("its a map")
//first find all the attributes and put them on the start token
for i := 0; i < len(node.Content); i += 2 {
key := node.Content[i]
value := node.Content[i+1]
if e.isAttribute(key.Value) {
if value.Kind == ScalarNode {
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
} else {
return fmt.Errorf("cannot use %v as attribute, only scalars are supported", value.Tag)
}
}
}
err := e.encodeStart(encoder, node, start)
if err != nil {
return err
}
//now we encode non attribute tokens
for i := 0; i < len(node.Content); i += 2 {
key := node.Content[i]
value := node.Content[i+1]
err := e.encodeComment(encoder, headAndLineComment(key))
if err != nil {
return err
}View on GitHub (pinned to 8b5af0694b)
Solutions
- Make the attribute value a scalar: `+attr: value`.
- Move the complex data to a child element (non-attribute key or the content key) instead of an attribute.
- Rename the key so it no longer starts with the attribute prefix if it is not meant to be an attribute.
- Change --xml-attribute-prefix so ordinary keys are not misinterpreted as attributes.
Example fix
// before
root:
+attrs: {a: 1}
// after
root:
+a: 1
content: {a: 1} Defensive patterns
Strategy: validation
Validate before calling
yq '.root | to_entries | select(.key | test("^\\+")) | any(.value | kind != "scalar")' in.yaml Type guard
// Go
func attributesAreScalar(m *yqlib.CandidateNode, prefix string) bool {
for i := 0; i < len(m.Content); i += 2 {
k, v := m.Content[i].Value, m.Content[i+1]
if strings.HasPrefix(k, prefix) && v.Kind != yqlib.ScalarNode { return false }
}
return true
} Try / catch
// Go
if err := enc.Encode(w, node); err != nil {
if strings.Contains(err.Error(), "only scalars are supported") {
// restructure attribute into a child element and retry
}
} Prevention
- Only assign scalar values to attribute-prefixed keys
- Use child elements (or the content key) for structured data
- Review XML round-trip output for attributes that became maps
When it happens
Trigger: Encoding `-o xml` a document such as `root: +attr: {a: 1}` or `+attr: [1,2]` — an attribute-prefixed key whose value is a MappingNode or SequenceNode.
Common situations: Round-tripping XML that originally had attributes with complex content; hand-authored YAML where an attribute-prefixed key was given a nested structure; tool-generated docs mixing attribute and content conventions.
Related errors
- cannot encode %v to XML - only maps can be encoded
- cannot encode %v as URI, can only operate on strings. Please
- cannot encode %v as URI, can only operate on strings. Please
- unsupported type %v
- no support for output format
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/ae1e11bdfb33ec7a.
Report an issue: GitHub.