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

  1. Add dir to the cache entry in config (e.g. dir = ":cacheDir" or an absolute path)
  2. Use a placeholder such as :cacheDir / :resource so Hugo resolves the path
  3. 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

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


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)