gohugoio/hugo · error

invalid filename

Error message

invalid filename

What it means

Thrown by the internal readFile helper (used by os.ReadFile) when filepath.Clean reduces the filename to empty, ".", or the OS path separator. This guards against reading the filesystem root or an empty path, which would be meaningless or unsafe.

Solutions

  1. Validate the path is non-empty and not a root marker before calling: {{ with $path }}{{ if not (eq $path "/") }}{{ readFile $path }}{{ end }}{{ end }}.
  2. Provide a sensible default file path.
  3. Check the source of the path variable (e.g. .Params) to ensure it is set.

Example fix

// before
{{ readFile .Params.path }}
// after
{{ with .Params.path }}{{ readFile . }}{{ end }}
Defensive patterns

Strategy: validation

Validate before calling

{{ with .Params.path }}{{ if and (ne . "") (ne . "/") (ne . ".") }}{{ readFile . }}{{ end }}{{ end }}

Prevention

When it happens

Trigger: Calling {{ readFile "" }}, {{ readFile "." }}, or {{ readFile "/" }}. Also when a templated path collapses to one of these after filepath.Clean (e.g. a path of all slashes or dots).

Common situations: Passing an unset param; a computed path that strips down to nothing; user-supplied path variables that are empty by mistake.

Related errors


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

Appendix: source

Thrown at tpl/os/os.go:82

func (ns *Namespace) Getenv(key any) (string, error) {
	skey, err := cast.ToStringE(key)
	if err != nil {
		return "", nil
	}

	if err = ns.deps.ExecHelper.Sec().CheckAllowedGetEnv(skey); err != nil {
		return "", err
	}

	return _os.Getenv(skey), nil
}

// readFile reads the file named by filename in the given filesystem
// and returns the contents as a string.
func readFile(fs afero.Fs, filename string) (string, error) {
	filename = filepath.Clean(filename)
	if filename == "" || filename == "." || filename == string(_os.PathSeparator) {
		return "", errors.New("invalid filename")
	}

	b, err := afero.ReadFile(fs, filename)
	if err != nil {
		return "", err
	}

	return string(b), nil
}

// ReadFile reads the file named by filename relative to the configured WorkingDir.
// It returns the contents as a string.
// There is an upper size limit set at 1 megabytes.
func (ns *Namespace) ReadFile(i any) (string, error) {
	s, err := cast.ToStringE(i)
	if err != nil {
		return "", err
	}

View on GitHub (pinned to 52c9bd7908)