gohugoio/hugo · error
failed to copy resources to vendor dir
Error message
failed to copy resources to vendor dir: %w
What it means
Returned by Client.Vendor when hugio.CopyDir fails copying the module's 'resources' directory (files.FolderResources) into _vendor, after the directory was confirmed to exist via Stat. Wrapped with %w. This is the post-mounts step that vendors the resource cache folder alongside mounts.
Solutions
- Examine the wrapped error for the OS-level cause.
- Fix permissions on the module's resources/ directory and re-run.
- Remove unneeded contents from resources/_gen before vendoring.
- Ensure _vendor is on a writable filesystem with enough space.
Example fix
# before hugo mod vendor # CopyDir on resources/ fails (perms) # after chmod -R u+r $(go env GOMODCACHE)/<module>@<ver>/resources hugo mod vendor
Defensive patterns
Strategy: try-catch
Validate before calling
// Check the module's resources dir is readable before vendoring.
func resourcesReadable(fs afero.Fs, dir string) error {
rd := filepath.Join(dir, "resources")
if _, err := fs.Stat(rd); err == nil {
f, err := fs.Open(rd)
if err != nil {
return err
}
f.Close()
}
return nil
} Try / catch
if err := client.Vendor(); err != nil {
if strings.Contains(err.Error(), "failed to copy resources to vendor dir") {
// inspect permissions/symlinks in module's resources/, fix, retry
}
} Prevention
- Avoid committing broken symlinks into a theme's resources/ dir.
- Ensure resources/ is readable in the module cache.
When it happens
Trigger: Running `hugo mod vendor` for a module that contains a 'resources/' directory whose recursive copy fails: unreadable files, broken symlinks, permission errors, or a write rejection on the vendor target.
Common situations: Theme modules shipping a resources/_gen image cache with restrictive permissions; broken symlinks in resources; read-only _vendor; large resources dir hitting disk limits on CI; cross-filesystem copy where afero lacks support.
Related errors
- failed to copy config dir to vendor dir
- failed to copy module file to vendor
- failed to copy module 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/e48b29a964168abd.
Report an issue: GitHub.
Appendix: source
Thrown at modules/client.go:266
} 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 {
if err := hugio.CopyDir(c.fs, resourcesDir, filepath.Join(vendorDir, t.PathVersionQuery(true), files.FolderResources), nil); err != nil {
return fmt.Errorf("failed to copy resources to vendor dir: %w", err)
}
}
// Include the config directory if present.
configDir := filepath.Join(dir, "config")
_, err = c.fs.Stat(configDir)
if err == nil {
if err := hugio.CopyDir(c.fs, configDir, filepath.Join(vendorDir, t.PathVersionQuery(true), "config"), nil); err != nil {
return fmt.Errorf("failed to copy config dir to vendor dir: %w", err)
}
}
// Also include any theme.toml or config.* or hugo.* files in the root.
configFiles, _ := afero.Glob(c.fs, filepath.Join(dir, "config.*"))
configFiles2, _ := afero.Glob(c.fs, filepath.Join(dir, "hugo.*"))
configFiles = append(configFiles, configFiles2...)
configFiles = append(configFiles, filepath.Join(dir, "theme.toml"))
for _, configFile := range configFiles {View on GitHub (pinned to 52c9bd7908)