golang/go · error
codehost.WorkDir: can't find or create lock file: %v
Error message
codehost.WorkDir: can't find or create lock file: %v
What it means
Thrown by codehost.WorkDir when lockedfile.MutexAt(lockfile).Lock() fails for the per-repo .lock file under GOMODCACHE/cache/vcs. The %v is the underlying error from the lock acquisition (usually permission or I/O). The lock serializes access to a cached VCS checkout.
Source
Thrown at src/cmd/go/internal/modfetch/codehost/codehost.go:248
key := typ + ":" + name
dir = filepath.Join(cfg.GOMODCACHE, "cache/vcs", fmt.Sprintf("%x", sha256.Sum256([]byte(key))))
xLog, buildX := cfg.BuildXWriter(ctx)
if buildX {
fmt.Fprintf(xLog, "mkdir -p %s # %s %s\n", filepath.Dir(dir), typ, name)
}
if err := os.MkdirAll(filepath.Dir(dir), 0777); err != nil {
return "", "", err
}
lockfile = dir + ".lock"
if buildX {
fmt.Fprintf(xLog, "# lock %s\n", lockfile)
}
unlock, err := lockedfile.MutexAt(lockfile).Lock()
if err != nil {
return "", "", fmt.Errorf("codehost.WorkDir: can't find or create lock file: %v", err)
}
defer unlock()
data, err := os.ReadFile(dir + ".info")
info, err2 := os.Stat(dir)
if err == nil && err2 == nil && info.IsDir() {
// Info file and directory both already exist: reuse.
have := strings.TrimSuffix(string(data), "\n")
if have != key {
return "", "", fmt.Errorf("%s exists with wrong content (have %q want %q)", dir+".info", have, key)
}
if buildX {
fmt.Fprintf(xLog, "# %s for %s %s\n", dir, typ, name)
}
return dir, lockfile, nil
}
// Info file or directory missing. Start from scratch.View on GitHub (pinned to b6b368adc5)
Solutions
- Check permissions on GOMODCACHE/cache/vcs: 'ls -la $(go env GOMODCACHE)/cache/vcs/'.
- Remove stale lock files: 'find $(go env GOMODCACHE)/cache/vcs -name *.lock -delete' (only when no go commands are running).
- On network filesystems, move GOMODCACHE to a local disk.
- Clear and rebuild the VCS cache: 'go clean -cache'.
Example fix
# before: lock file owned by root on a shared FS $ go get example.com/mod ... can't find or create lock file: ... # after sudo chown -R $USER $(go env GOMODCACHE)/cache go get example.com/mod
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
// Retry on transient lock failures with backoff
func withLockRetry(fn func() error) error {
for i := 0; i < 3; i++ {
err := fn()
if err == nil { return nil }
if isLockErr(err) && i < 2 {
time.Sleep(time.Duration(1<<i) * time.Second)
continue
}
return err
}
return fmt.Errorf("lock retry exhausted")
} Prevention
- Run 'go clean -cache' periodically to remove stale lock files.
- On network filesystems, relocate GOMODCACHE to local disk.
- Avoid running many parallel go commands against a shared cache on NFS.
- Ensure the cache directory is user-owned (chown -R $USER).
When it happens
Trigger: Concurrent or sequential go commands accessing the same cached VCS repo when the lock file or its parent directory is inaccessible, read-only, or on a filesystem that doesn't support the locking mechanism.
Common situations: Cache directory chowned to another user; NFS/CIFS mounts with broken advisory locking; antivirus or security software holding the file open on Windows; disk full preventing lock file creation.
Related errors
- failed to create cache directory: %w
- could not create module cache: %w
- GOMODCACHE entry is relative; must be absolute path: %q
- could not create module cache: %q is not a directory
- error opening file created by 'svn export': %v
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/9f42c341bf147edb.
Report an issue: GitHub.