gohugoio/hugo · error
must provide cache Dir
Error message
must provide cache Dir
What it means
When decoding the filecache configuration from Hugo config, after mapstructure decodes a cache entry, if the Dir field is empty the loader rejects it with 'must provide cache Dir'. Every named cache must declare a directory.
Solutions
- Add dir to the cache entry in config (e.g. dir = ":cacheDir" or an absolute path)
- Use a placeholder such as :cacheDir / :resource so Hugo resolves the path
- Validate the full caches block against the Hugo documentation
Example fix
# before [caches.assets] maxAge = "24h" # after [caches.assets] dir = ":cacheDir" maxAge = "24h"
Defensive patterns
Strategy: validation
Validate before calling
for name, cc := range cacheConfigs {
if cc.Dir == "" {
return fmt.Errorf("cache %q missing dir", name)
}
} Prevention
- Always pair a cache maxAge with a dir in Hugo config
- Use Hugo's documented dir placeholders (:cacheDir, :resource)
When it happens
Trigger: A caching config block (e.g. [caches.assets]) sets fields like maxAge but omits dir, leaving Dir empty after decode and hitting filecache_config.go:244-245.
Common situations: User overrides a cache's maxAge but forgets dir; a typo renames dir to something else; copying a partial config example from docs.
Related errors
- cache dir contains unresolved placeholders
- config not set
- failed to decode filecache config
- failed to decode $_hugo_config in template
- fatal filecache error
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/cf9be4215d1cacd7.
Report an issue: GitHub.
Appendix: source
Thrown at cache/filecache/filecache_config.go:245
}
dc := &mapstructure.DecoderConfig{
Result: &cc,
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
WeaklyTypedInput: true,
}
decoder, err := mapstructure.NewDecoder(dc)
if err != nil {
return c, err
}
if err := decoder.Decode(v); err != nil {
return nil, fmt.Errorf("failed to decode filecache config: %w", err)
}
if cc.Dir == "" {
return c, errors.New("must provide cache Dir")
}
c[k] = cc
}
for k, v := range c {
dir := filepath.ToSlash(filepath.Clean(v.Dir))
hadSlash := strings.HasPrefix(dir, "/")
parts := strings.Split(dir, "/")
for i, part := range parts {
if strings.HasPrefix(part, ":") {
resolved, isResource, err := resolveDirPlaceholder(fs, bcfg, part)
if err != nil {
return c, err
}
if isResource {View on GitHub (pinned to 52c9bd7908)