gohugoio/hugo · error

failed to open non-content file

Error message

failed to open non-content file: %w

What it means

While copying non-content files out of a directory-based archetype bundle (create/content.go:188), Hugo calls fi.Meta().Open() on each 'other' file. This wraps the Open failure, which is typically a permission/IO/symlink problem on an asset inside the archetype.

Solutions

  1. Inspect the archetype bundle for broken symlinks and remove or fix them.
  2. Verify read permission on every file under the archetypes/ directory.
  3. Recreate the offending asset file in the archetype bundle.
  4. Reduce the archetype bundle to isolate which file triggers the open failure.

Example fix

# before: archetypes/default/index.md -> missing image symlink
archetypes/default/img.png -> /nonexistent/real.png

# after: ship a real file
$ cp real.png archetypes/default/img.png
Defensive patterns

Strategy: validation

Validate before calling

// Verify every file in an archetype bundle is openable before NewContent.
func ValidateArchetypeBundleReadable(fs afero.Fs, dir string) error {
    return afero.Walk(fs, dir, func(p string, info os.FileInfo, err error) error {
        if err != nil { return err }
        if info.IsDir() { return nil }
        f, err := fs.Open(p)
        if err != nil { return fmt.Errorf("%s: %w", p, err) }
        return f.Close()
    })
}

Try / catch

if err := create.NewContent(h, kind, targetPath, force); err != nil {
    return err
}

Prevention

When it happens

Trigger: An archetype directory bundle contains an asset file that cannot be opened: revoked read permission, a broken/dead symlink, a file removed mid-copy, or a virtual-FS path that is stale.

Common situations: Broken symlink inside archetypes/; archetype copied from another OS with missing target; archetype on a mount that became unreadable.

Related errors


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

Appendix: source

Thrown at create/content.go:190

	}

	if err := b.h.Build(hugolib.BuildCfg{NoBuildLock: true, SkipRender: true, ContentInclusionFilter: contentInclusionFilter}); err != nil {
		return err
	}

	for i, filename := range contentTargetFilenames {
		if err := b.applyArcheType(filename, b.dirMap.contentFiles[i]); err != nil {
			return err
		}
	}

	// Copy the rest as is.
	for _, fi := range b.dirMap.otherFiles {
		meta := fi.Meta()

		in, err := meta.Open()
		if err != nil {
			return fmt.Errorf("failed to open non-content file: %w", err)
		}
		targetFilename := filepath.Join(baseDir, b.targetPath, strings.TrimPrefix(fi.Meta().Filename, b.archetypeFi.Meta().Filename))
		targetDir := filepath.Dir(targetFilename)

		if err := b.sourceFs.MkdirAll(targetDir, 0o777); err != nil && !os.IsExist(err) {
			return fmt.Errorf("failed to create target directory for %q: %w", targetDir, err)
		}

		out, err := b.sourceFs.Create(targetFilename)
		if err != nil {
			return err
		}

		_, err = io.Copy(out, in)
		if err != nil {
			return err
		}

View on GitHub (pinned to 52c9bd7908)