gohugoio/hugo · error

invalid filename

Error message

invalid filename

What it means

The `os.ReadFile` template function cleans the given path and rejects it if the result is empty, ".", or the bare path separator — i.e. it doesn't name an actual file. This guards against reading the working directory root or a meaningless path.

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 8a468df065)

Solutions

  1. Guard the call: `{{ with $path }}{{ os.ReadFile . }}{{ end }}` so empty values are skipped.
  2. Check where the path variable comes from (front matter param, site config) and set or default it (`default "data/x.txt" .Params.file`).
  3. Ensure the path points to a real file relative to the project working directory, not a directory.

Example fix

{{/* before */}}
{{ $c := os.ReadFile .Params.snippet }}
{{/* after */}}
{{ with .Params.snippet }}{{ $c := os.ReadFile . }}{{ end }}
Defensive patterns

Strategy: validation

Validate before calling

{{ $path := "data/notes.txt" }}
{{ if and $path (fileExists $path) }}
  {{ $content := readFile $path }}
{{ end }}

Try / catch

{{ with try (os.ReadFile $path) }}
  {{ with .Err }}{{ warnf "readFile %q: %s" $path . }}{{ else }}{{ $content := .Value }}{{ end }}
{{ end }}

Prevention

When it happens

Trigger: `{{ os.ReadFile "" }}`, `{{ os.ReadFile "." }}`, `{{ os.ReadFile "/" }}`, or a path that filepath.Clean collapses to one of those (e.g. "./", "foo/..").

Common situations: A template variable used as the filename is empty because a page param or site config value is unset; string concatenation producing "" or "/"; iterating over params where some entries lack a path field.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/74772cb5edab2d12.json. Report an issue: GitHub ↗.