golang/go · error

could not create module cache: %w

Error message

could not create module cache: %w

What it means

Thrown inside checkCacheDir when os.Stat(GOMODCACHE) fails with an error that is NOT 'file does not exist' — meaning a permission error, I/O error, or path error. The %w wraps the underlying OS error so the root cause (e.g. 'permission denied') is visible. This runs inside a sync.Once so the check only happens once per process.

Source

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

// error is returned if it does not.
func checkCacheDir(ctx context.Context) error {
	if cfg.GOMODCACHE == "" {
		// modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
		// is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
		return fmt.Errorf("module cache not found: neither GOMODCACHE nor GOPATH is set")
	}
	if !filepath.IsAbs(cfg.GOMODCACHE) {
		counterErrorsGOMODCACHEEntryRelative.Inc()
		return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE)
	}

	// os.Stat is slow on Windows, so we only call it once to prevent unnecessary
	// I/O every time this function is called.
	statCacheOnce.Do(func() {
		fi, err := os.Stat(cfg.GOMODCACHE)
		if err != nil {
			if !os.IsNotExist(err) {
				statCacheErr = fmt.Errorf("could not create module cache: %w", err)
				return
			}
			if err := os.MkdirAll(cfg.GOMODCACHE, 0o777); err != nil {
				statCacheErr = fmt.Errorf("could not create module cache: %w", err)
				return
			}
			return
		}
		if !fi.IsDir() {
			statCacheErr = fmt.Errorf("could not create module cache: %q is not a directory", cfg.GOMODCACHE)
			return
		}
	})
	return statCacheErr
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Run 'go env GOMODCACHE' to see the current path, then 'ls -la' on the parent directory to check permissions.
  2. Fix ownership/permissions: 'sudo chown -R $(whoami) <parent_dir>' or 'chmod +x <parent_dir>'.
  3. If the path is on a stale or unmounted filesystem, remount or re-point GOMODCACHE with 'go env -w GOMODCACHE=/new/abs/path'.
  4. Check for broken symlinks in the path with 'readlink -f <GOMODCACHE>'.

Example fix

# before: GOMODCACHE parent owned by root
sudo mkdir -p /root/.cache/go-build
# after
sudo chown -R $USER:$USER $(dirname $(go env GOMODCACHE))
# or set a writable location
go env -w GOMODCACHE=$HOME/go/pkg/mod
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking go commands, verify GOMODCACHE is stat-able
import (
    "os"
    "fmt"
    "path/filepath"
)

func validateGOMODCACHE(gomodcache string) error {
    if gomodcache == "" {
        return fmt.Errorf("GOMODCACHE is empty")
    }
    if !filepath.IsAbs(gomodcache) {
        return fmt.Errorf("GOMODCACHE must be absolute: %q", gomodcache)
    }
    if _, err := os.Stat(gomodcache); err != nil && !os.IsNotExist(err) {
        return fmt.Errorf("GOMODCACHE stat failed (non-NotExist): %w", err)
    }
    return nil
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling any go command that touches the module cache (go build, go mod download, go get) when the GOMODCACHE path is inaccessible: parent directory lacks execute permission, the path crosses a broken symlink, or the filesystem returns an I/O error.

Common situations: GOMODCACHE points to a directory whose parent has restrictive permissions (e.g. owned by root), a NFS mount that went stale, a docker volume mounted read-only, or a broken symlink in the path.

Related errors


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