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

  1. Populate the root element with actual child content, or delete the placeholder data file until it has data.
  2. 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.
  3. 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

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


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/b597432e97864382.json. Report an issue: GitHub ↗.