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

  1. Pass at least one concrete file path to ParseFiles.
  2. Validate len(files) > 0 before calling ParseFiles and handle the empty case explicitly.
  3. If sourcing from a glob, use ParseGlob instead and let it report the no-match error, or check the glob result first.
  4. 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

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


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/48fdb6f2f8540f04. Report an issue: GitHub.