gohugoio/hugo · error
is a root folder and not allowed as cache dir
Error message
%q is a root folder and not allowed as cache dir
What it means
DecodeConfig rejects a cache directory that resolves to a filesystem root (filecache_config.go:282-283), detected when stripping the volume name leaves a single character (e.g. / or C:\). This is a safety guard because cache pruning deletes files, and operating on root would be catastrophic.
Solutions
- Point cacheDir to a subdirectory such as /home/user/.cache/hugo, never /
- Verify the resolved path has at least one path component beyond root
- Check that cacheDir config is not accidentally set to / or empty
Example fix
# before cacheDir = "/" # after cacheDir = "/var/cache/hugo"
Defensive patterns
Strategy: validation
Validate before calling
// Reject root paths before they reach the config decoder.
func isRootPath(dir string) bool {
withoutVol := strings.TrimPrefix(dir, filepath.VolumeName(dir))
return len(withoutVol) <= 1
} Prevention
- Never set cacheDir to / or a bare drive root
- Always include at least one subdirectory component in cache paths
- Review config after migrations that might reset cacheDir
When it happens
Trigger: Configuring cacheDir or a cache dir to resolve to / (Unix) or a drive root (Windows), e.g. cacheDir = "/".
Common situations: Empty or accidentally-rooted cacheDir; misconfigured placeholder resolution that lands on root; config migration errors.
Related errors
- must resolve to an absolute directory
- cache dir contains unresolved placeholders
- failed to decode filecache config
- is not a valid cache name
- is not a valid placeholder (valid values are :cacheDir or…
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/34cb46e9ea404f0d.
Report an issue: GitHub.
Appendix: source
Thrown at cache/filecache/filecache_config.go:283
}
parts[i] = resolved
}
}
dir = path.Join(parts...)
if hadSlash {
dir = "/" + dir
}
v.DirCompiled = filepath.Clean(filepath.FromSlash(dir))
if !v.IsResourceDir {
if isOsFs && !filepath.IsAbs(v.DirCompiled) {
return c, fmt.Errorf("%q must resolve to an absolute directory", v.DirCompiled)
}
// Avoid cache in root, e.g. / (Unix) or c:\ (Windows)
if len(strings.TrimPrefix(v.DirCompiled, filepath.VolumeName(v.DirCompiled))) == 1 {
return c, fmt.Errorf("%q is a root folder and not allowed as cache dir", v.DirCompiled)
}
}
if !strings.HasPrefix(v.DirCompiled, "_gen") {
// We do cache eviction (file removes) and since the user can set
// his/hers own cache directory, we really want to make sure
// we do not delete any files that do not belong to this cache.
// We do add the cache name as the root, but this is an extra safe
// guard. We skip the files inside /resources/_gen/ because
// that would be breaking.
v.DirCompiled = filepath.Join(v.DirCompiled, FilecacheRootDirname, k)
} else {
v.DirCompiled = filepath.Join(v.DirCompiled, k)
}
c[k] = v
}
View on GitHub (pinned to 52c9bd7908)