gohugoio/hugo · error
failed to copy module to vendor dir
Error message
failed to copy module to vendor dir: %w
What it means
Returned by Client.Vendor when hugio.CopyDir fails copying a mount whose source is a directory into _vendor. Fires after the source Stat succeeded (so the dir exists) but the recursive copy failed. Wrapped with %w.
Solutions
- Inspect the wrapped error for the OS-level cause (permission, ENOSPC, symlink).
- Fix permissions on the module cache (chmod) and ensure the working dir is writable.
- Remove or repair broken symlinks in the offending module directory.
- Free disk space or raise tmpfs size if ENOSPC.
Example fix
# before: module cache not readable sudo chown -R $USER $(go env GOMODCACHE) # after hugo mod vendor # now succeeds
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check writability of the vendor target.
func vendorDirWritable(dir string) error {
probe := filepath.Join(dir, ".writeprobe")
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
return os.WriteFile(probe, []byte("x"), 0o644)
} Try / catch
if err := client.Vendor(); err != nil {
if strings.Contains(err.Error(), "failed to copy module to vendor dir") {
// unwrap to inspect permission/space/symlink cause
}
} Prevention
- Ensure the project dir and module cache are writable by the Hugo user.
- Avoid broken symlinks inside theme directories.
- Run vendor on a clean checkout.
When it happens
Trigger: Running `hugo mod vendor` where a mount source is a directory and CopyDir hits a permission error, an unreadable sub-entry, a broken symlink, or the target filesystem (afero.Fs) rejects a write (e.g. read-only overlay, disk full).
Common situations: Filesystem permission issues in the module cache; broken symlinks inside a theme's assets/layouts dir; running vendor on a read-only working directory; CI with a tmpfs that fills up; Windows path-length limits on deeply nested vendor targets.
Related errors
- failed to copy config dir to vendor dir
- failed to copy module file to vendor
- failed to copy resources to vendor dir
- failed to make target dir
- failed to copy to
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/7e4a38fd9442d83e.
Report an issue: GitHub.
Appendix: source
Thrown at modules/client.go:246
if t.Mounts() == nil {
return fmt.Errorf("cannot vendor module %q, need at least one mount", t.PathVersionQuery(false))
}
fmt.Fprintln(&modulesContent, "# "+t.PathVersionQuery(true)+" "+t.Version())
dir := t.Dir()
for _, mount := range t.Mounts() {
sourceFilename := filepath.Join(dir, mount.Source)
targetFilename := filepath.Join(vendorDir, t.PathVersionQuery(true), mount.Source)
fi, err := c.fs.Stat(sourceFilename)
if err != nil {
return fmt.Errorf("failed to vendor module: %w", err)
}
if fi.IsDir() {
if err := hugio.CopyDir(c.fs, sourceFilename, targetFilename, nil); err != nil {
return fmt.Errorf("failed to copy module to vendor dir: %w", err)
}
} else {
targetDir := filepath.Dir(targetFilename)
if err := c.fs.MkdirAll(targetDir, 0o755); err != nil {
return fmt.Errorf("failed to make target dir: %w", err)
}
if err := hugio.CopyFile(c.fs, sourceFilename, targetFilename); err != nil {
return fmt.Errorf("failed to copy module file to vendor: %w", err)
}
}
}
// Include the resource cache if present.
resourcesDir := filepath.Join(dir, files.FolderResources)
_, err := c.fs.Stat(resourcesDir)
if err == nil {View on GitHub (pinned to 52c9bd7908)