gohugoio/hugo · error

fileInfo: %w

Error message

fileInfo: %w

What it means

Wrapped by fileInfo.Open() when the underlying source file metadata's Open() call fails. The fileInfo struct wraps a source.File; calling Open() delegates to the file's FileInfo().Meta().Open() and re-wraps any error with the 'fileInfo:' prefix for tracing. It is a low-level I/O failure surfaced while Hugo reads a content/source file (e.g. during page reads or the source walk).

Source

Thrown at hugolib/fileInfo.go:31

package hugolib

import (
	"fmt"

	"github.com/spf13/afero"

	"github.com/gohugoio/hugo/source"
)

type fileInfo struct {
	*source.File
}

func (fi *fileInfo) Open() (afero.File, error) {
	f, err := fi.FileInfo().Meta().Open()
	if err != nil {
		err = fmt.Errorf("fileInfo: %w", err)
	}

	return f, err
}

func (fi *fileInfo) Lang() string {
	return fi.File.Lang()
}

func (fi *fileInfo) String() string {
	if fi == nil || fi.File == nil {
		return ""
	}
	return fi.Path()
}

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Check the wrapped error (%w) — it names the real OS-level cause (ENOENT, EACCES, etc.) and the path.
  2. If running `hugo server`, re-save the file or confirm the file still exists on disk after editor operations.
  3. Verify filesystem permissions/ownership on the content directory and that the mount target paths in config exist.
  4. Remove or fix broken symlinks inside content/ and module mounts.

Example fix

// before: mount points to a removed dir
[[mounts]]
source = "content/posts/drafts"  // deleted on disk

// after: remove the stale mount or restore the directory
[[mounts]]
source = "content/posts"
Defensive patterns

Strategy: try-catch

Validate before calling

// Before opening, stat the file via the same afero fs to fail early:
if _, err := fi.FileInfo().Meta().Fs.Stat(path); err != nil {
    return fmt.Errorf("pre-check stat failed: %w", err)
}

Type guard

// Hugo is Go; treat any non-nil error from Open() as the signal.
// No type narrowing needed — callers should errors.Is/As the wrapped cause:
if errors.Is(err, fs.ErrNotExist) { /* handle missing file */ }

Try / catch

f, err := fi.Open()
if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) {
        // I/O-level cause; log path and skip or fail the page
        h.Log.Errorf("open %s: %v", perr.Path, perr)
        return
    }
    return err
}
defer f.Close()

Prevention

When it happens

Trigger: Produced when (fi *fileInfo).Open() is invoked and fi.FileInfo().Meta().Open() returns a non-nil error — typically because the backing afero filesystem cannot read the file (deleted, permissions, broken symlink, missing mount target).

Common situations: A content file is removed or renamed mid-build (common during `hugo server` watch while the editor saves/deletes); a content directory mount points at a path the process cannot read; a symlink loop or broken symlink inside content; permission errors after a chmod/chown in CI.

Related errors


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