{"record":{"id":"7b9c9463e2d74165","repo":"gohugoio/hugo","slug":"xml-root-element-s-must-be-a-map-object-got-t","errorCode":null,"errorMessage":"XML root element '%s' must be a map/object, got %T","messagePattern":"XML root element '(.+?)' must be a map/object, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"parser/metadecoders/decoder.go","lineNumber":306,"sourceCode":"\t\txmlRoot, err = xml.NewMapXml(data)\n\n\t\tvar xmlValue map[string]any\n\t\tif err == nil {\n\t\t\txmlRootName, err := xmlRoot.Root()\n\t\t\tif err != nil {\n\t\t\t\treturn toFileError(f, data, fmt.Errorf(\"failed to unmarshal XML: %w\", err))\n\t\t\t}\n\n\t\t\t// Get the root value and verify it's a map\n\t\t\trootValue := xmlRoot[xmlRootName]\n\t\t\tif rootValue == nil {\n\t\t\t\treturn toFileError(f, data, fmt.Errorf(\"XML root element '%s' has no value\", xmlRootName))\n\t\t\t}\n\n\t\t\t// Type check before conversion\n\t\t\tmapValue, ok := rootValue.(map[string]any)\n\t\t\tif !ok {\n\t\t\t\treturn toFileError(f, data, fmt.Errorf(\"XML root element '%s' must be a map/object, got %T\", xmlRootName, rootValue))\n\t\t\t}\n\t\t\txmlValue = mapValue\n\t\t}\n\n\t\tswitch v := v.(type) {\n\t\tcase *map[string]any:\n\t\t\t*v = xmlValue\n\t\tcase *any:\n\t\t\t*v = xmlValue\n\t\t}\n\tcase TOML:\n\t\terr = toml.Unmarshal(data, v)\n\tcase YAML:\n\t\treturn UnmarshalYaml(data, v)\n\tcase CSV:\n\t\treturn d.unmarshalCSV(data, v)\n\n\tdefault:","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/parser/metadecoders/decoder.go#L288-L324","documentation":"Thrown in the XML branch of Decoder.UnmarshalTo (parser/metadecoders/decoder.go:306) when the parsed XML root element's value is not a map[string]any. Hugo expects the root to contain child elements (which mxj turns into a map); a root whose direct value is a bare string, number, or array fails this type check. The %T names the actual type.","triggerScenarios":"An XML document like <root>just text</root> where the root's value is a string, or <root>42</root> where it is a number; a root containing a single text node rather than child elements; mxj representing a list-only root as []any.","commonSituations":"Treating a simple scalar XML value as a structured data file; an export tool emitting text content at the root instead of wrapping it in child elements; a feed returning a single value rather than a collection.","solutions":["Wrap the root's value in child elements so the root maps to an object: <root><value>text</value></root>.","If the data is scalar, use a different format (JSON/TOML) or parse it manually.","Re-export the XML ensuring the root contains only element children."],"exampleFix":"<!-- before -->\n<root>some text</root>\n\n<!-- after -->\n<root>\n  <value>some text</value>\n</root>","handlingStrategy":"type-guard","validationCode":"// Ensure the XML root maps to an object (has child elements).\nfunc xmlRootIsObjectish(data []byte) bool {\n    return bytes.Count(data, []byte(\"</\")) > 0\n}","typeGuard":null,"tryCatchPattern":"if err := dec.UnmarshalTo(data, metadecoders.XML, &m); err != nil {\n    return fmt.Errorf(\"XML root must be an object: %w\", err)\n}","preventionTips":["Wrap scalar values in child elements.","Use JSON/TOML for scalar data.","Re-export XML with element children only."],"tags":["xml","metadecoders","type-mismatch","data","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}