{"record":{"id":"9f42c341bf147edb","repo":"golang/go","slug":"codehost-workdir-can-t-find-or-create-lock-file","errorCode":null,"errorMessage":"codehost.WorkDir: can't find or create lock file: %v","messagePattern":"codehost\\.WorkDir: can't find or create lock file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/codehost/codehost.go","lineNumber":248,"sourceCode":"\tkey := typ + \":\" + name\n\tdir = filepath.Join(cfg.GOMODCACHE, \"cache/vcs\", fmt.Sprintf(\"%x\", sha256.Sum256([]byte(key))))\n\n\txLog, buildX := cfg.BuildXWriter(ctx)\n\tif buildX {\n\t\tfmt.Fprintf(xLog, \"mkdir -p %s # %s %s\\n\", filepath.Dir(dir), typ, name)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(dir), 0777); err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\n\tlockfile = dir + \".lock\"\n\tif buildX {\n\t\tfmt.Fprintf(xLog, \"# lock %s\\n\", lockfile)\n\t}\n\n\tunlock, err := lockedfile.MutexAt(lockfile).Lock()\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"codehost.WorkDir: can't find or create lock file: %v\", err)\n\t}\n\tdefer unlock()\n\n\tdata, err := os.ReadFile(dir + \".info\")\n\tinfo, err2 := os.Stat(dir)\n\tif err == nil && err2 == nil && info.IsDir() {\n\t\t// Info file and directory both already exist: reuse.\n\t\thave := strings.TrimSuffix(string(data), \"\\n\")\n\t\tif have != key {\n\t\t\treturn \"\", \"\", fmt.Errorf(\"%s exists with wrong content (have %q want %q)\", dir+\".info\", have, key)\n\t\t}\n\t\tif buildX {\n\t\t\tfmt.Fprintf(xLog, \"# %s for %s %s\\n\", dir, typ, name)\n\t\t}\n\t\treturn dir, lockfile, nil\n\t}\n\n\t// Info file or directory missing. Start from scratch.","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/codehost/codehost.go#L230-L266","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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'."],"exampleFix":"# before: lock file owned by root on a shared FS\n$ go get example.com/mod\n... can't find or create lock file: ...\n# after\nsudo chown -R $USER $(go env GOMODCACHE)/cache\ngo get example.com/mod","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"// Retry on transient lock failures with backoff\nfunc withLockRetry(fn func() error) error {\n    for i := 0; i < 3; i++ {\n        err := fn()\n        if err == nil { return nil }\n        if isLockErr(err) && i < 2 {\n            time.Sleep(time.Duration(1<<i) * time.Second)\n            continue\n        }\n        return err\n    }\n    return fmt.Errorf(\"lock retry exhausted\")\n}","preventionTips":["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)."],"tags":["filesystem","permissions","locking","vcs-cache","gomodcache"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}