gohugoio/hugo · error

failed to create file caches from configuration: %w

Error message

failed to create file caches from configuration: %w

What it means

Raised in fromLoadConfigResult (allconfig.go:1175) when filecache.NewCaches cannot build Hugo's file caches from the compiled `caches` config. After all language configs are decoded, Hugo instantiates the cache set (getjson, getcsv, images, assets, modules, etc.) with resolved directories and TTLs; failure means a cache entry is invalid or its directory cannot be created.

Source

Thrown at config/allconfig/allconfig.go:1175

			langConfigMap[k] = clone
		case hmaps.ParamsMergeStrategy:

		default:
			panic(fmt.Sprintf("unknown type in languages config: %T", v))

		}
	}

	bcfg.PublishDir = all.PublishDir
	res.BaseConfig = bcfg
	all.CommonDirs.CacheDir = bcfg.CacheDir
	for _, l := range langConfigMap {
		l.CommonDirs.CacheDir = bcfg.CacheDir
	}

	caches, err := filecache.NewCaches(all.Caches, fs)
	if err != nil {
		return nil, fmt.Errorf("failed to create file caches from configuration: %w", err)
	}

	cm := &Configs{
		Base:              all,
		LanguageConfigMap: langConfigMap,
		LoadingInfo:       res,
		FileCaches:        caches,
		IsMultihost:       isMultihost,
	}

	return cm, nil
}

func decodeConfigFromParams(fs afero.Fs, logger loggers.Logger, bcfg config.BaseConfig, p config.Provider, target *Config, keys []string) error {
	var decoderSetups []decodeWeight

	if len(keys) == 0 {
		for _, v := range allDecoderSetups {

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Read the wrapped error to see which cache or path failed, and fix that `[caches.*]` entry (valid dir with :cacheDir/:project tokens, valid maxAge duration).
  2. Ensure the cache directory (config cacheDir or HUGO_CACHEDIR) exists and is writable by the build user.
  3. Set cacheDir explicitly to a writable location in restricted environments (e.g. HUGO_CACHEDIR=/tmp/hugo_cache).
  4. Remove custom caches config to fall back to defaults and reintroduce entries one at a time.

Example fix

# before
[caches.getjson]
maxAge = "forever"
# after
[caches.getjson]
maxAge = -1  # -1 means never expire
Defensive patterns

Strategy: validation

Validate before calling

// Validate [caches] entries before load: each cache needs a known name,
// a valid dir template and a parseable maxAge duration
for name, c := range cfg.GetStringMap("caches") {
    m := c.(map[string]any)
    if ma, ok := m["maxAge"].(string); ok {
        if _, err := time.ParseDuration(ma); err != nil && ma != "-1" {
            return fmt.Errorf("caches.%s.maxAge invalid: %v", name, err)
        }
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to create file caches") {
    return fmt.Errorf("inspect the [caches] section: check dir placeholders (:cacheDir/:resourceDir) and maxAge values: %w", err)
}

Prevention

When it happens

Trigger: An invalid `[caches.<name>]` config (unparseable maxAge, bad dir template token), a cacheDir/resourceDir path that cannot be created due to permissions or a read-only filesystem, or an unknown cache name in config.

Common situations: CI/containers with read-only or non-writable cache locations, HUGO_CACHEDIR pointing to an inaccessible path, typos in caches config, or disk-full/permission issues under /tmp or the user cache dir.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/95096b447af6dd5c.json. Report an issue: GitHub ↗.