{"id":"63d68990f349077e","repo":"gohugoio/hugo","slug":"unsupported-data-file-extension-q","errorCode":null,"errorMessage":"unsupported data file extension %q","messagePattern":"unsupported data file extension %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hugolib/content_map.go","lineNumber":333,"sourceCode":"\t\t}\n\n\t\tm.treePages.InsertWithLock(pm.pathInfo.Base(), pm)\n\t}\n\treturn\n}\n\nfunc (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *BuildCfg) (pageCount uint64, resourceCount uint64, addErr error) {\n\tmeta := fi.Meta()\n\tpi := meta.PathInfo\n\n\tm.s.Log.Trace(logg.StringFunc(\n\t\tfunc() string {\n\t\t\treturn fmt.Sprintf(\"insert pages from data file: %q\", fi.Meta().Filename)\n\t\t},\n\t))\n\n\tif !files.IsGoTmplExt(pi.Ext()) {\n\t\taddErr = fmt.Errorf(\"unsupported data file extension %q\", pi.Ext())\n\t\treturn\n\t}\n\n\tsitesMatrix := fi.Meta().SitesMatrix\n\n\ts := m.s.h.resolveFirstSite(sitesMatrix)\n\th := s.h\n\n\tcontentAdapter := s.pageMap.treePagesFromTemplateAdapters.Get(pi.Base())\n\tvar rebuild bool\n\tif contentAdapter != nil {\n\t\t// Rebuild\n\t\tcontentAdapter = contentAdapter.CloneForGoTmpl(fi)\n\t\trebuild = true\n\t} else {\n\t\tcontentAdapter = pagesfromdata.NewPagesFromTemplate(\n\t\t\tpagesfromdata.PagesFromTemplateOptions{\n\t\t\t\tGoTmplFi: fi,","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/hugolib/content_map.go#L315-L351","documentation":"addPagesFromGoTmplFi handles files classified as TypeContentData — content adapters that generate pages from data. Hugo requires these to be Go template files (files.IsGoTmplExt, i.e. .gotmpl); any other extension on a file in that role is rejected. It prevents Hugo from executing a non-template file as a pages-from-data adapter.","triggerScenarios":"Placing a file named like a content adapter (e.g. _content.<ext>) under content/ where the path parser classifies it as TypeContentData but the extension is not .gotmpl — for example _content.yaml, _content.json, or _content.tmpl.","commonSituations":"Misnaming the content adapter file _content.tmpl or _content.html instead of _content.gotmpl; assuming the pages-from-data feature accepts raw YAML/JSON data files directly; migrating examples from blog posts that used a different extension.","solutions":["Rename the adapter file to _content.gotmpl — that is the only supported extension for pages-from-data adapters.","If the file is plain data, move it to the data/ directory (or load it inside the .gotmpl via resources) instead of content/.","Check the docs for content adapters (hugo v0.126+) if the feature is new to the project."],"exampleFix":"// before\ncontent/posts/_content.yaml\n// after\ncontent/posts/_content.gotmpl  (loads the YAML via resources.Get and calls .AddPage)","handlingStrategy":"validation","validationCode":"var dataExts = map[string]bool{\".json\": true, \".toml\": true, \".yaml\": true, \".yml\": true, \".xml\": true, \".csv\": true}\nif !dataExts[filepath.Ext(path)] {\n    return fmt.Errorf(\"unsupported data file %q\", path)\n}","typeGuard":"func isDataFile(path string) bool {\n    switch filepath.Ext(path) {\n    case \".json\", \".toml\", \".yaml\", \".yml\", \".xml\", \".csv\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := site.Build(); err != nil {\n    if strings.Contains(err.Error(), \"unsupported data file extension\") {\n        // remove or rename the offending file in data/\n    }\n    return err\n}","preventionTips":["Only place decodable formats (json, toml, yaml, xml, csv) under data/","Keep README, .md, .txt and editor backup files (~, .swp) out of the data directory","Add a CI check that lists data/ files with unexpected extensions"],"tags":["hugo","content-adapter","gotmpl","configuration"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}