gohugoio/hugo · error

failed to create cache dir: %w

Error message

failed to create cache dir: %w

What it means

helpers.GetCacheDir resolves Hugo's cache directory (from the `cacheDir` config, HUGO_CACHEDIR, or a default) and creates it with MkdirAll if it doesn't exist. This error wraps the underlying filesystem error when that MkdirAll fails, meaning Hugo cannot set up the directory used for module downloads, image processing cache, and getresource caches.

Source

Thrown at helpers/path.go:253

	}

	return f, err
}

// GetCacheDir returns a cache dir from the given filesystem and config.
// The dir will be created if it does not exist.
func GetCacheDir(fs afero.Fs, cacheDir string) (string, error) {
	cacheDir = cacheDirDefault(cacheDir)

	if cacheDir != "" {
		exists, err := DirExists(cacheDir, fs)
		if err != nil {
			return "", err
		}
		if !exists {
			err := fs.MkdirAll(cacheDir, 0o777) // Before umask
			if err != nil {
				return "", fmt.Errorf("failed to create cache dir: %w", err)
			}
		}
		return cacheDir, nil
	}

	const hugoCacheBase = "hugo_cache"

	// Avoid filling up the home dir with Hugo cache dirs from development.
	if !htesting.IsTest {
		userCacheDir, err := os.UserCacheDir()
		if err == nil {
			cacheDir := filepath.Join(userCacheDir, hugoCacheBase)
			if err := fs.Mkdir(cacheDir, 0o777); err == nil || os.IsExist(err) {
				return cacheDir, nil
			}
		}
	}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Check the wrapped error detail (permission denied, read-only file system, not a directory) and point `cacheDir`/HUGO_CACHEDIR at a writable location, e.g. a path under the CI workspace or $HOME.
  2. In containers, mount a writable volume and set `HUGO_CACHEDIR=/tmp/hugo_cache` (or similar) so cache creation succeeds.
  3. If a file exists at the cache path, remove or rename it so a directory can be created.
  4. Fix ownership/permissions on the parent directory (`chown`/`chmod`) if the path itself is correct.

Example fix

# before (CI)
hugo --minify   # HUGO_CACHEDIR=/var/hugo_cache, not writable by build user

# after
export HUGO_CACHEDIR=$GITHUB_WORKSPACE/.hugo_cache
hugo --minify
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the cache dir is creatable/writable before invoking Hugo
if err := os.MkdirAll(cacheDir, 0o755); err != nil { log.Fatalf("cacheDir unusable: %v", err) }
f, err := os.CreateTemp(cacheDir, "probe*"); if err == nil { f.Close(); os.Remove(f.Name()) }

Try / catch

if err := run(); err != nil {
    if errors.Is(err, fs.ErrPermission) || strings.Contains(err.Error(), "failed to create cache dir") {
        // point cacheDir at a writable location and retry once
    }
}

Prevention

When it happens

Trigger: MkdirAll on the resolved cache path returns an error: the configured `cacheDir` points into a location the user lacks write permission for, a path component exists as a regular file, the disk is full, or the path is on a read-only mount. Occurs at startup of any hugo build/server command that initializes caches.

Common situations: CI containers running as a non-root user with `cacheDir` or HUGO_CACHEDIR set to a root-owned path like /var/hugo_cache; read-only root filesystems in hardened containers (need a writable volume for the cache); Windows/网络 drives with restricted ACLs; a stale file occupying the configured cache path.

Related errors


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