gohugoio/hugo · warning

failed to prune cache %q: %w

Error message

failed to prune cache %q: %w

What it means

`Caches.Prune` iterates every configured file cache (getjson, getcsv, images, assets, modules, getresource) and removes expired or unused entries; it operates directly on the filesystem. If pruning one cache fails for any reason other than the directory not existing, the loop stops and wraps the failure with the cache's key so you know which cache was being cleaned.

Source

Thrown at cache/filecache/filecache_pruner.go:43

	"github.com/spf13/afero"
)

// Prune removes expired and unused items from this cache.
// The last one requires a full build so the cache usage can be tracked.
// Note that we operate directly on the filesystem here, so this is not
// thread safe.
func (c Caches) Prune() (int, error) {
	counter := 0
	for k, cache := range c {
		count, err := cache.Prune(false)

		counter += count

		if err != nil {
			if herrors.IsNotExist(err) {
				continue
			}
			return counter, fmt.Errorf("failed to prune cache %q: %w", k, err)
		}

	}

	return counter, nil
}

// Prune removes expired and unused items from this cache.
// If force is set, everything will be removed not considering expiry time.
func (c *Cache) Prune(force bool) (int, error) {
	if c.cfg.entryIsDir {
		return c.pruneRootDirs(force)
	}
	if err := c.init(); err != nil {
		return 0, err
	}

	counter := 0

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Check the cache name in the error and fix permissions on that subdirectory under your cache root (`chown -R` to the build user).
  2. Stop concurrent Hugo processes sharing the same cache dir before running `--gc`.
  3. If the cache is corrupted, delete the named cache subdirectory (or the whole cache root) manually and rebuild.
Defensive patterns

Strategy: try-catch

Validate before calling

# Confirm cache subdirs are intact and writable before pruning:
find "$HUGO_CACHEDIR" -maxdepth 1 -type d ! -writable

Try / catch

if err := prune(); err != nil {
    // %q names the specific cache that failed — often safe to delete it wholesale
    log.Printf("prune failed: %v — removing that cache dir manually and continuing", err)
}

Prevention

When it happens

Trigger: Running `hugo --gc` or `hugo server` with GC enabled: `cache.Prune(false)` on a specific cache returns a non-IsNotExist error — e.g. permission denied deleting an entry, an entry directory locked by another process, or filesystem I/O errors while walking/removing cache files.

Common situations: Cache directories created by a different user (root-built Docker layer, then non-root prune); antivirus or backup tools holding locks on cache files on Windows; NFS/network-mounted cache dirs with flaky delete semantics; two concurrent Hugo builds sharing one cache dir (Prune is documented as not thread safe).

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/c30b49cd7bdf0d64.json. Report an issue: GitHub ↗.