golang/go · error

failed to create cache directory: %w

Error message

failed to create cache directory: %w

What it means

Thrown by `modfetch.SideLock` when `os.MkdirAll` fails to create the `cache/lock` parent directory inside GOMODCACHE. SideLock acquires a mutex on a file in the module cache to serialize edits to files outside the cache (go.sum, go.mod). If the cache directory structure cannot be created — due to permissions, disk full, or path issues — this wraps the underlying OS error with %w.

Source

Thrown at src/cmd/go/internal/modfetch/cache.go:178

	}
	if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
		return nil, err
	}
	return lockedfile.MutexAt(path).Lock()
}

// SideLock locks a file within the module cache that previously guarded
// edits to files outside the cache, such as go.sum and go.mod files in the
// user's working directory.
// If err is nil, the caller MUST eventually call the unlock function.
func SideLock(ctx context.Context) (unlock func(), err error) {
	if err := checkCacheDir(ctx); err != nil {
		return nil, err
	}

	path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")
	if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
		return nil, fmt.Errorf("failed to create cache directory: %w", err)
	}

	return lockedfile.MutexAt(path).Lock()
}

// A cachingRepo is a cache around an underlying Repo,
// avoiding redundant calls to ModulePath, Versions, Stat, Latest, and GoMod (but not CheckReuse or Zip).
// It is also safe for simultaneous use by multiple goroutines
// (so that it can be returned from Lookup multiple times).
// It serializes calls to the underlying Repo.
type cachingRepo struct {
	path          string
	versionsCache par.ErrCache[string, *Versions]
	statCache     par.ErrCache[string, *RevInfo]
	latestCache   par.ErrCache[struct{}, *RevInfo]
	gomodCache    par.ErrCache[string, []byte]

	once     sync.Once

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Check and fix permissions on GOMODCACHE: `chmod -R u+w $(go env GOMODCACHE)`
  2. Ensure GOMODCACHE points to a writable directory
  3. Free disk space if full
  4. Verify the path is valid and accessible: `ls -la $(go env GOMODCACHE)/cache/`

Example fix

# before: GOMODCACHE points to read-only location
export GOMODCACHE=/usr/local/go/pkg/mod
# after: point to writable location
export GOMODCACHE=$HOME/go/pkg/mod
Defensive patterns

Strategy: validation

Validate before calling

// Verify cache directory is writable before operations
import "os"

func ensureCacheWritable() error {
    cacheDir := os.Getenv("GOMODCACHE")
    if cacheDir == "" {
        cacheDir = filepath.Join(os.Getenv("GOPATH"), "pkg", "mod")
    }
    testFile := filepath.Join(cacheDir, "cache", ".writetest")
    return os.WriteFile(testFile, []byte("ok"), 0644)
}

Prevention

When it happens

Trigger: Calling SideLock when GOMODCACHE/cache/ cannot be created. MkdirAll fails due to: permission denied on a parent directory, read-only filesystem, disk full, invalid path characters, or GOMODCACHE pointing to a location that can't be created.

Common situations: GOMODCACHE set to a read-only directory; insufficient permissions on the cache root; disk full; GOMODCACHE on a network mount with write failures; containerized environments with volume permission issues.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/8a012b6c8f80be66. Report an issue: GitHub.