gohugoio/hugo · error
failled to create base cache directory: %s
Error message
failled to create base cache directory: %s
What it means
On first use, each file cache lazily creates its base directory via `c.Fs.MkdirAll("", 0o777)` inside a `sync.Once`. If that mkdir fails (and the failure isn't 'already exists'), the error is stored as `initErr` and returned from every subsequent cache operation, so all reads/writes through that cache fail with this message (note the upstream typo 'failled').
Source
Thrown at cache/filecache/filecache.go:111
afero.File
unlock func()
}
func (l *lockedFile) Close() error {
defer l.unlock()
return l.File.Close()
}
func (c *Cache) init() error {
if c == nil {
panic("cache is nil")
}
c.initOnce.Do(func() {
c.isInited = true
// Create the base dir if it does not exist.
if err := c.Fs.MkdirAll("", 0o777); err != nil && !os.IsExist(err) {
err = fmt.Errorf("failled to create base cache directory: %s", err)
c.initErr = err
}
})
return c.initErr
}
// WriteCloser returns a transactional writer into the cache.
// It's important that it's closed when done.
func (c *Cache) WriteCloser(id string) (ItemInfo, io.WriteCloser, error) {
if err := c.init(); err != nil {
return ItemInfo{}, nil, err
}
id = cleanID(id)
c.entryLocker.Lock(id)
info := ItemInfo{Name: id}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Point the cache at a writable location: set `HUGO_CACHEDIR=/tmp/hugo_cache` or `cacheDir` in config to a directory the build user can create.
- Fix permissions/ownership on the existing cache root (`chown`/`chmod` the directory).
- In containers, mount a writable volume for the cache dir or run the build with a writable `$TMPDIR`.
Example fix
# before (CI container, read-only home) hugo --minify # after export HUGO_CACHEDIR=/tmp/hugo_cache hugo --minify
Defensive patterns
Strategy: validation
Validate before calling
# Verify the configured cache directory's parent is writable:
CACHE=${HUGO_CACHEDIR:-$(hugo config | sed -n 's/^cachedir *= *//p')}
mkdir -p "$CACHE" && test -w "$CACHE" Try / catch
if err := build(); err != nil {
if strings.Contains(err.Error(), "create base cache directory") {
log.Println("set HUGO_CACHEDIR to a writable path")
}
return err
} Prevention
- Explicitly set HUGO_CACHEDIR (or caches config) to a directory the build user owns
- In containers/read-only filesystems, mount a writable volume for the cache
- Don't point cacheDir at root-owned system paths
- Pre-create the cache dir in CI images
When it happens
Trigger: Any cache access (`WriteCloser`, `GetOrCreate`, `ReadOrCreate`) whose lazy `init()` runs `MkdirAll` on the cache's base path and gets a permission, read-only-filesystem, or disk-full error — the cache root derives from `cacheDir` config, `HUGO_CACHEDIR`, or the platform default (e.g. `$TMPDIR/hugo_cache`).
Common situations: Docker/CI containers running as non-root with `cacheDir` pointing at an unwritable path; read-only root filesystems (Kubernetes `readOnlyRootFilesystem`); Netlify/Vercel builds with unusual `HUGO_CACHEDIR`; a cache path that collides with an existing regular file.
Related errors
- failed to prune cache %q: %w
- failed to save file %q:: %w
- failed to resolve output path %q: %w
- failed to save file %q: %s
- failed to create workingDir: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/69c853a89ebde244.json.
Report an issue: GitHub ↗.