{"record":{"id":"48fdb6f2f8540f04","repo":"gohugoio/hugo","slug":"html-template-no-files-named-in-call-to-parsefile","errorCode":null,"errorMessage":"html/template: no files named in call to ParseFiles","messagePattern":"html/template: no files named in call to ParseFiles","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/internal/go_templates/htmltemplate/template.go","lineNumber":408,"sourceCode":"//\n// When parsing multiple files with the same name in different directories,\n// the last one mentioned will be the one that results.\n//\n// ParseFiles returns an error if t or any associated template has already been executed.\nfunc (t *Template) ParseFiles(filenames ...string) (*Template, error) {\n\treturn parseFiles(t, readFileOS, filenames...)\n}\n\n// parseFiles is the helper for the method and function. If the argument\n// template is nil, it is created from the first file.\nfunc parseFiles(t *Template, readFile func(string) (string, []byte, error), filenames ...string) (*Template, error) {\n\tif err := t.checkCanParse(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(filenames) == 0 {\n\t\t// Not really a problem, but be consistent.\n\t\treturn nil, fmt.Errorf(\"html/template: no files named in call to ParseFiles\")\n\t}\n\tfor _, filename := range filenames {\n\t\tname, b, err := readFile(filename)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ts := string(b)\n\t\t// First template becomes return value if not already defined,\n\t\t// and we use that one for subsequent New calls to associate\n\t\t// all the templates together. Also, if this file has the same name\n\t\t// as t, this file becomes the contents of t, so\n\t\t//  t, err := New(name).Funcs(xxx).ParseFiles(name)\n\t\t// works. Otherwise we create a new template associated with t.\n\t\tvar tmpl *Template\n\t\tif t == nil {\n\t\t\tt = New(name)\n\t\t}\n\t\tif name == t.Name() {","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/internal/go_templates/htmltemplate/template.go#L390-L426","documentation":"Returned by parseFiles (backing ParseFiles and the method t.ParseFiles) when no filename arguments were supplied. Parsing requires at least one file; an empty argument list is treated as a programmer error rather than a no-op.","triggerScenarios":"Calling template.ParseFiles() or t.ParseFiles() with zero variadic string arguments, e.g. ParseFiles() with an empty slice or no args.","commonSituations":"Building the filename list dynamically and passing an empty slice; a glob that resolved to zero names being splatted into ParseFiles; refactoring that dropped the file argument.","solutions":["Pass at least one concrete file path to ParseFiles.","Validate len(files) > 0 before calling ParseFiles and handle the empty case explicitly.","If sourcing from a glob, use ParseGlob instead and let it report the no-match error, or check the glob result first.","Add a unit test asserting ParseFiles is never called with an empty list."],"exampleFix":"// before\nfiles := []string{} // resolved to nothing\nt, err := template.ParseFiles(files...) // error\n\n// after\nif len(files) == 0 {\n    return fmt.Errorf(\"no template files to parse\")\n}\nt, err := template.ParseFiles(files...)","handlingStrategy":"validation","validationCode":"func parseFilesOrErr(files []string) (*template.Template, error) {\n    if len(files) == 0 {\n        return nil, fmt.Errorf(\"ParseFiles called with no files\")\n    }\n    return template.ParseFiles(files...)\n}","typeGuard":null,"tryCatchPattern":"t, err := template.ParseFiles(files...)\nif err != nil && strings.Contains(err.Error(), \"no files named in call to ParseFiles\") {\n    // resolve files again and retry with explicit list\n    files, _ = filepath.Glob(pattern)\n    if len(files) == 0 { return nil, err }\n    t, err = template.ParseFiles(files...)\n}","preventionTips":["Check len(files) > 0 before splatting into ParseFiles.","Prefer ParseGlob when sourcing from a pattern.","Unit-test the file-list builder so it never yields empty."],"tags":["go","html-template","parse-files","validation"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}