{"id":"cf9be4215d1cacd7","repo":"gohugoio/hugo","slug":"must-provide-cache-dir","errorCode":null,"errorMessage":"must provide cache Dir","messagePattern":"must provide cache Dir","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cache/filecache/filecache_config.go","lineNumber":245,"sourceCode":"\t\t}\n\n\t\tdc := &mapstructure.DecoderConfig{\n\t\t\tResult:           &cc,\n\t\t\tDecodeHook:       mapstructure.StringToTimeDurationHookFunc(),\n\t\t\tWeaklyTypedInput: true,\n\t\t}\n\n\t\tdecoder, err := mapstructure.NewDecoder(dc)\n\t\tif err != nil {\n\t\t\treturn c, err\n\t\t}\n\n\t\tif err := decoder.Decode(v); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to decode filecache config: %w\", err)\n\t\t}\n\n\t\tif cc.Dir == \"\" {\n\t\t\treturn c, errors.New(\"must provide cache Dir\")\n\t\t}\n\n\t\tc[k] = cc\n\n\t}\n\n\tfor k, v := range c {\n\t\tdir := filepath.ToSlash(filepath.Clean(v.Dir))\n\t\thadSlash := strings.HasPrefix(dir, \"/\")\n\t\tparts := strings.Split(dir, \"/\")\n\n\t\tfor i, part := range parts {\n\t\t\tif strings.HasPrefix(part, \":\") {\n\t\t\t\tresolved, isResource, err := resolveDirPlaceholder(fs, bcfg, part)\n\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 {","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/cache/filecache/filecache_config.go#L227-L263","documentation":"Returned by filecache.DecodeConfig when a [caches.<name>] override in site config decodes successfully but ends up with an empty Dir. The user's override replaced the default config for that cache (defaults are merged per-key via mapstructure into the existing entry), and an explicitly empty dir would leave Hugo nowhere to store cache files, so it fails fast rather than guessing a location.","triggerScenarios":"Setting `dir = \"\"` explicitly under a caches entry, or a decode that clears the inherited default Dir; any [caches.X] map whose resulting merged config has Dir == \"\".","commonSituations":"Trying to 'disable' a cache by blanking its dir instead of setting maxAge = 0, YAML quirks that yield an empty string for dir, or templated/env-substituted config where the variable expands to empty (e.g. dir = \"${HUGO_CACHEDIR}\" unset).","solutions":["Remove the empty `dir` line so the cache inherits its default (typically :cacheDir/:project-based).","To disable a cache, set `maxAge = 0` instead of blanking the directory.","If using env-var substitution, ensure the variable is set before running hugo."],"exampleFix":"# before\n[caches.images]\ndir = \"\"\n# after\n[caches.images]\ndir = \":cacheDir/images\"","handlingStrategy":"validation","validationCode":"for name, c := range cachesConfig {\n    if strings.TrimSpace(c.Dir) == \"\" {\n        return fmt.Errorf(\"cache %q: dir must be set\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set dir when overriding a cache entry; overriding only maxAge with an empty dir is invalid","Copy the default caches config from the docs as a starting point","Prefer omitting a cache entry entirely over setting an empty dir"],"tags":["hugo","filecache","config","validation"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}