{"id":"21824f43a0ec4122","repo":"gohugoio/hugo","slug":"q-must-resolve-to-an-absolute-directory","errorCode":null,"errorMessage":"%q must resolve to an absolute directory","messagePattern":"%q must resolve to an absolute directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cache/filecache/filecache_config.go","lineNumber":278,"sourceCode":"\t\t\t\tif err != nil {\n\t\t\t\t\treturn c, err\n\t\t\t\t}\n\t\t\t\tif isResource {\n\t\t\t\t\tv.IsResourceDir = true\n\t\t\t\t}\n\t\t\t\tparts[i] = resolved\n\t\t\t}\n\t\t}\n\n\t\tdir = path.Join(parts...)\n\t\tif hadSlash {\n\t\t\tdir = \"/\" + dir\n\t\t}\n\t\tv.DirCompiled = filepath.Clean(filepath.FromSlash(dir))\n\n\t\tif !v.IsResourceDir {\n\t\t\tif isOsFs && !filepath.IsAbs(v.DirCompiled) {\n\t\t\t\treturn c, fmt.Errorf(\"%q must resolve to an absolute directory\", v.DirCompiled)\n\t\t\t}\n\n\t\t\t// Avoid cache in root, e.g. / (Unix) or c:\\ (Windows)\n\t\t\tif len(strings.TrimPrefix(v.DirCompiled, filepath.VolumeName(v.DirCompiled))) == 1 {\n\t\t\t\treturn c, fmt.Errorf(\"%q is a root folder and not allowed as cache dir\", v.DirCompiled)\n\t\t\t}\n\t\t}\n\n\t\tif !strings.HasPrefix(v.DirCompiled, \"_gen\") {\n\t\t\t// We do cache eviction (file removes) and since the user can set\n\t\t\t// his/hers own cache directory, we really want to make sure\n\t\t\t// we do not delete any files that do not belong to this cache.\n\t\t\t// We do add the cache name as the root, but this is an extra safe\n\t\t\t// guard. We skip the files inside /resources/_gen/ because\n\t\t\t// that would be breaking.\n\t\t\tv.DirCompiled = filepath.Join(v.DirCompiled, FilecacheRootDirname, k)\n\t\t} else {\n\t\t\tv.DirCompiled = filepath.Join(v.DirCompiled, k)","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/cache/filecache/filecache_config.go#L260-L296","documentation":"Returned by filecache.DecodeConfig after placeholder resolution when a cache directory that is not the resource dir does not compile to an absolute filesystem path, and Hugo is running on a real OS filesystem. Because Hugo performs cache eviction (deletes files) in these directories, it insists on unambiguous absolute paths to avoid operating relative to an unpredictable working directory.","triggerScenarios":"A caches.<name>.dir set to a relative path like `cache/images` or `./mycache` (without :cacheDir/:resourceDir/:project placeholders producing an absolute root); only enforced when the fs is afero.OsFs, so in-memory test filesystems skip it.","commonSituations":"Users writing relative cache dirs expecting them to be project-relative, CI configs that hardcode `tmp/cache`, or a :cacheDir placeholder resolving to an empty/relative bcfg.CacheDir because cacheDir was misconfigured.","solutions":["Use an absolute path for the cache dir, or a placeholder that resolves absolutely, e.g. `dir = \":cacheDir/images\"`.","Set a valid top-level `cacheDir` (or HUGO_CACHEDIR env var) so :cacheDir resolves to an absolute directory.","For project-local resource caching use `:resourceDir`, which is exempt from this check."],"exampleFix":"# before\n[caches.images]\ndir = \"cache/images\"\n# after\n[caches.images]\ndir = \":cacheDir/images\"","handlingStrategy":"validation","validationCode":"if !filepath.IsAbs(resolvedDir) {\n    return fmt.Errorf(\"cache dir %q must resolve to an absolute path\", resolvedDir)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start cache dirs with :cacheDir or :resourceDir so they always resolve absolute","Avoid bare relative paths like \"cache/images\" in caches.*.dir","Verify HUGO_CACHEDIR / cacheDir itself is an absolute path when set via env"],"tags":["hugo","filecache","config","filesystem","paths"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}