gohugoio/hugo · error
failed to unmarshal XML
Error message
failed to unmarshal XML: %w
What it means
Thrown in the XML branch of Decoder.UnmarshalTo (parser/metadecoders/decoder.go:294) when xmlRoot.Root() (from clbanning/mxj) returns an error after parsing. This means the XML could be parsed into a Map but extracting the root element name failed — typically indicating malformed, empty, or non-element XML. The error is wrapped via toFileError to attach file context.
Solutions
- Validate the XML is well-formed with a single root element using xmllint or a browser.
- Ensure the file has actual element content, not just an <?xml?> declaration.
- Re-fetch or re-export the source XML if it is truncated/corrupt.
- If the data isn't truly XML, rename/reformat the file to its actual format.
Example fix
<!-- before --> <?xml version="1.0"?> <!-- after --> <?xml version="1.0"?> <root> <item>value</item> </root>
Defensive patterns
Strategy: validation
Validate before calling
// Basic XML well-formedness check before UnmarshalTo.
func looksLikeXML(data []byte) bool {
return bytes.Contains(data, []byte("<")) && bytes.Contains(data, []byte(">"))
} Try / catch
if err := dec.UnmarshalTo(data, metadecoders.XML, &m); err != nil {
return fmt.Errorf("invalid XML data: %w", err)
} Prevention
- Validate XML with xmllint before placing under data/.
- Ensure a single root element with content.
- Re-fetch corrupt feeds.
When it happens
Trigger: Feeding UnmarshalTo XML data that is a fragment, an XML declaration only (<?xml?> with no root element), mixed/invalid content, or text that mxj parses but cannot identify a single root for; loading a .xml data file with broken structure.
Common situations: An XML data file under data/ that is empty or contains only a declaration; an externally-fetched XML feed that is malformed; copy-paste introducing a stray tag; encoding issues (BOM, wrong charset) confusing the parser.
Related errors
- XML root element ' ' has no value
- XML root element ' ' must be a map/object, got %T
- cannot unmarshal CSV into %T: expected at least a header…
- cannot unmarshal CSV into %T: header row contains duplicate…
- unmarshal failed
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/32d333034a560765.
Report an issue: GitHub.
Appendix: source
Thrown at parser/metadecoders/decoder.go:294
// UnmarshalTo unmarshals data in format f into v.
func (d Decoder) UnmarshalTo(data []byte, f Format, v any) error {
var err error
switch f {
case ORG:
err = d.unmarshalORG(data, v)
case JSON:
err = json.Unmarshal(data, v)
case XML:
var xmlRoot xml.Map
xmlRoot, err = xml.NewMapXml(data)
var xmlValue map[string]any
if err == nil {
xmlRootName, err := xmlRoot.Root()
if err != nil {
return toFileError(f, data, fmt.Errorf("failed to unmarshal XML: %w", err))
}
// Get the root value and verify it's a map
rootValue := xmlRoot[xmlRootName]
if rootValue == nil {
return toFileError(f, data, fmt.Errorf("XML root element '%s' has no value", xmlRootName))
}
// Type check before conversion
mapValue, ok := rootValue.(map[string]any)
if !ok {
return toFileError(f, data, fmt.Errorf("XML root element '%s' must be a map/object, got %T", xmlRootName, rootValue))
}
xmlValue = mapValue
}
switch v := v.(type) {
case *map[string]any:View on GitHub (pinned to 52c9bd7908)