{"record":{"id":"c30b49cd7bdf0d64","repo":"gohugoio/hugo","slug":"failed-to-prune-cache-q-w","errorCode":null,"errorMessage":"failed to prune cache %q: %w","messagePattern":"failed to prune cache %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cache/filecache/filecache_pruner.go","lineNumber":43,"sourceCode":"\t\"github.com/spf13/afero\"\n)\n\n// Prune removes expired and unused items from this cache.\n// The last one requires a full build so the cache usage can be tracked.\n// Note that we operate directly on the filesystem here, so this is not\n// thread safe.\nfunc (c Caches) Prune() (int, error) {\n\tcounter := 0\n\tfor k, cache := range c {\n\t\tcount, err := cache.Prune(false)\n\n\t\tcounter += count\n\n\t\tif err != nil {\n\t\t\tif herrors.IsNotExist(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn counter, fmt.Errorf(\"failed to prune cache %q: %w\", k, err)\n\t\t}\n\n\t}\n\n\treturn counter, nil\n}\n\n// Prune removes expired and unused items from this cache.\n// If force is set, everything will be removed not considering expiry time.\nfunc (c *Cache) Prune(force bool) (int, error) {\n\tif c.cfg.entryIsDir {\n\t\treturn c.pruneRootDirs(force)\n\t}\n\tif err := c.init(); err != nil {\n\t\treturn 0, err\n\t}\n\n\tcounter := 0","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/cache/filecache/filecache_pruner.go#L25-L61","documentation":"Caches.Prune (filecache_pruner.go:32-48) iterates every named cache and calls Cache.Prune(false). If a cache returns an error that is not a 'file not found' error, it is wrapped with the cache name and propagated. Pruning walks the filesystem removing expired and unused entries; I/O failures surface here.","triggerScenarios":"Running hugo --gc after a build when the cache filesystem has permission errors, locked files, or I/O failures during the walk and remove operations.","commonSituations":"Permission issues on cache files created by a different user; files locked by another running Hugo process; disk errors; stale cache from a previous OS/user.","solutions":["Check and fix read/write/execute permissions on the entire cache directory tree","Ensure no other Hugo process is running and holding locks on cache files","Clear the cache manually (rm -rf the cache dir) and rebuild","Run hugo --gc with the same user/permissions that created the cache"],"exampleFix":"# before: cache owned by root, run as normal user\nhugo --gc\n# after: fix ownership first\nsudo chown -R $USER:$USER ~/.cache/hugo && hugo --gc","handlingStrategy":"try-catch","validationCode":"// Check cache directory health before running hugo --gc.\nfunc checkCacheTree(dir string) error {\n    return filepath.Walk(dir, func(p string, fi os.FileInfo, err error) error {\n        if err != nil {\n            return err\n        }\n        return nil\n    })\n}","typeGuard":null,"tryCatchPattern":"// Catch and report the prune error without aborting the whole build.\nif n, err := caches.Prune(); err != nil {\n    log.Printf(\"warning: cache prune partially failed: %v (%d items pruned)\", err, n)\n} else {\n    log.Printf(\"pruned %d cache items\", n)\n}","preventionTips":["Run hugo --gc as the same user that owns the cache","Avoid running multiple Hugo instances against the same cache simultaneously","Periodically clear the cache to avoid locked/stale-file accumulation"],"tags":["cache","filecache","prune","gc","filesystem","permissions","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}