gohugoio/hugo · error

failled to create base cache directory

Error message

failled to create base cache directory: %s

What it means

During lazy file-cache initialization, Cache.init calls c.Fs.MkdirAll("", 0o777) to create the cache base directory (filecache.go:110). If MkdirAll fails with a non-existence-ignorable error, it is stored as initErr and returned on every subsequent cache operation. Note the message contains a typo ('failled').

Solutions

  1. Check and fix write permissions on the configured cacheDir
  2. Set cacheDir to a writable location via --cacheDir flag or cacheDir in config
  3. If running in a container, ensure the cache volume is mounted writable

Example fix

# before: read-only cache dir
hugo --cacheDir /opt/hugo-cache
# after: writable cache dir
hugo --cacheDir /tmp/hugo-cache
Defensive patterns

Strategy: validation

Validate before calling

// Verify the cache dir is writable before starting Hugo.
func checkCacheDirWritable(dir string) error {
    info, err := os.Stat(dir)
    if os.IsNotExist(err) {
        return os.MkdirAll(dir, 0o755)
    }
    if err != nil {
        return err
    }
    if !info.IsDir() {
        return fmt.Errorf("%s is not a directory", dir)
    }
    return os.WriteFile(filepath.Join(dir, ".write_test"), []byte("x"), 0o644)
}

Try / catch

// The init error surfaces on the first cache operation; check it early.
if err := cache.GetOrCreate(...); err != nil {
    if strings.Contains(err.Error(), "create base cache directory") {
        log.Fatal("fix cache dir permissions: ", err)
    }
}

Prevention

When it happens

Trigger: The resolved cache filesystem path is read-only, lacks write/execute permissions, or the path is invalid for directory creation.

Common situations: Running Hugo as a user lacking write permission to the cache dir; read-only container/CI filesystem; cacheDir pointing to a read-only mounted volume; disk quota exceeded.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/69c853a89ebde244. Report an issue: GitHub.

Appendix: 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 52c9bd7908)