gohugoio/hugo · error
html/template: no files named in call to ParseFiles
Error message
html/template: no files named in call to ParseFiles
What it means
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.
Source
Thrown at tpl/internal/go_templates/htmltemplate/template.go:408
//
// When parsing multiple files with the same name in different directories,
// the last one mentioned will be the one that results.
//
// ParseFiles returns an error if t or any associated template has already been executed.
func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
return parseFiles(t, readFileOS, filenames...)
}
// parseFiles is the helper for the method and function. If the argument
// template is nil, it is created from the first file.
func parseFiles(t *Template, readFile func(string) (string, []byte, error), filenames ...string) (*Template, error) {
if err := t.checkCanParse(); err != nil {
return nil, err
}
if len(filenames) == 0 {
// Not really a problem, but be consistent.
return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
}
for _, filename := range filenames {
name, b, err := readFile(filename)
if err != nil {
return nil, err
}
s := string(b)
// First template becomes return value if not already defined,
// and we use that one for subsequent New calls to associate
// all the templates together. Also, if this file has the same name
// as t, this file becomes the contents of t, so
// t, err := New(name).Funcs(xxx).ParseFiles(name)
// works. Otherwise we create a new template associated with t.
var tmpl *Template
if t == nil {
t = New(name)
}
if name == t.Name() {View on GitHub (pinned to 52c9bd7908)
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.
Example fix
// before
files := []string{} // resolved to nothing
t, err := template.ParseFiles(files...) // error
// after
if len(files) == 0 {
return fmt.Errorf("no template files to parse")
}
t, err := template.ParseFiles(files...) Defensive patterns
Strategy: validation
Validate before calling
func parseFilesOrErr(files []string) (*template.Template, error) {
if len(files) == 0 {
return nil, fmt.Errorf("ParseFiles called with no files")
}
return template.ParseFiles(files...)
} Try / catch
t, err := template.ParseFiles(files...)
if err != nil && strings.Contains(err.Error(), "no files named in call to ParseFiles") {
// resolve files again and retry with explicit list
files, _ = filepath.Glob(pattern)
if len(files) == 0 { return nil, err }
t, err = template.ParseFiles(files...)
} Prevention
- 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.
When it happens
Trigger: Calling template.ParseFiles() or t.ParseFiles() with zero variadic string arguments, e.g. ParseFiles() with an empty slice or no args.
Common situations: 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.
Related errors
- the seed value (%v) must be a non-negative integer
- the number of requested values (%v) must be a non-negative i
- the maximum requested value (%v) must be a non-negative inte
- html/template: cannot Clone %q after it has executed
- html/template: cannot Parse after Execute
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/48fdb6f2f8540f04.
Report an issue: GitHub.