gohugoio/hugo · error
XML root element '%s' has no value
Error message
XML root element '%s' has no value
What it means
After successfully identifying the XML root element name, Hugo looks up that root's value in the mxj-produced map; if the value is nil, the root element exists but contains nothing Hugo can turn into data. Since Hugo's XML unmarshaling must yield a map of the root's children, an empty/self-closing root gives it nothing to return, so it fails rather than silently producing an empty result.
Source
Thrown at parser/metadecoders/decoder.go:300
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:
*v = xmlValue
case *any:
*v = xmlValue
}
case TOML:
err = toml.Unmarshal(data, v)View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Populate the root element with actual child content, or delete the placeholder data file until it has data.
- For remote feeds that can legitimately be empty, guard in the template: check the raw content for meaningful children before calling transform.Unmarshal, and handle the empty case explicitly.
- If the source is an API, confirm the query/endpoint is correct — an empty root often means the request matched nothing or hit the wrong URL.
Example fix
<!-- before (data/items.xml) --> <items/> <!-- after --> <items> <item><name>First</name></item> </items>
Defensive patterns
Strategy: validation
Validate before calling
# Reject empty-root XML before use xmllint --xpath 'boolean(/*/node())' data.xml # prints false for <root/> with no children
Try / catch
if err != nil && strings.Contains(err.Error(), "has no value") {
// the XML document's root element is empty — treat as missing data, fail the build input
} Prevention
- Ensure XML data files/feeds contain at least one child element or text under the root, not just `<root/>`
- Check remote feeds for empty responses (0 items) before unmarshalling and fail fast with a clear message
- Add an ingest-time assertion that parsed data is non-empty before templates consume it
When it happens
Trigger: Unmarshaling XML whose root element is empty — `<root/>` or `<root></root>` with no child elements, attributes, or text — via a `.xml` data file or `transform.Unmarshal`. The error names the offending root element.
Common situations: Remote APIs or RSS/Atom feeds returning an empty result set as a bare self-closing root element; placeholder data files committed before content was added; XML generated by a script that produced no records.
Related errors
- failed to unmarshal XML: %w
- unmarshal failed: %w
- cannot unmarshal CSV into %T: expected at least a header row
- can't evaluate an invalid value
- unmarshal takes 1 or 2 arguments
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/b597432e97864382.json.
Report an issue: GitHub ↗.