gohugoio/hugo · error
failed to copy module to vendor dir: %w
Error message
failed to copy module to vendor dir: %w
What it means
In `hugo mod vendor` (modules/client.go:246), when a mount source is a directory, Hugo recursively copies it into _vendor/<module-path>/ via hugio.CopyDir. Any I/O failure during that recursive copy surfaces as this wrapped error and aborts vendoring.
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 8a468df065)
Solutions
- Check the wrapped error for the failing path and whether it's a read (source) or write (target) failure.
- Ensure the project directory is writable and has free disk space; delete a partially written _vendor and retry.
- Fix permissions on the module cache (go clean -modcache then re-download if it's corrupted).
- On Windows, exclude the project from real-time AV scanning while vendoring.
Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the module source dir exists and is readable
if fi, err := os.Stat(mod.Dir()); err != nil || !fi.IsDir() {
return fmt.Errorf("module dir %q not accessible: %v", mod.Dir(), err)
} Try / catch
if err := client.Vendor(); err != nil {
if strings.Contains(err.Error(), "failed to copy module to vendor dir") {
// usually a filesystem issue: permissions, symlinks, or missing module cache
return fmt.Errorf("run 'hugo mod download' first, then re-vendor: %w", err)
}
return err
} Prevention
- Download modules (`hugo mod get` / `hugo mod download`) before vendoring so the module cache is populated
- Avoid symlinks inside module content directories — copy semantics may not follow them
- Check GOMODCACHE permissions; the cache is read-only by default which is fine for reads but confirm the destination side is writable
When it happens
Trigger: hugio.CopyDir(c.fs, sourceFilename, targetFilename, nil) fails while copying a mounted directory tree — permission errors, unreadable files, disk full, or files disappearing mid-copy.
Common situations: Read-only or root-owned files inside the Go module cache (GOMODCACHE stores modules read-only, though reads normally suffice); no write permission or no space in the project's _vendor directory; antivirus/file-lock interference on Windows; symlinks or special files inside the mounted tree.
Related errors
- failed to make target dir: %w
- failed to vendor module: %w
- failed to copy module file to vendor: %w
- failed to copy resources to vendor dir: %w
- failed to copy config dir to vendor dir: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/7e4a38fd9442d83e.json.
Report an issue: GitHub ↗.