{"record":{"id":"9c80827be4a434a2","repo":"twpayne/chezmoi","slug":"open-s-failed-to-acquire-lock-w","errorCode":null,"errorMessage":"open %s: failed to acquire lock: %w","messagePattern":"open (.+?): failed to acquire lock: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/chezmoi/boltpersistentstate.go","lineNumber":236,"sourceCode":"\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn b.Put(key, value)\n\t})\n}\n\n// open opens b's database if it is not already open, creating it if needed.\nfunc (b *BoltPersistentState) open() error {\n\tif b.db != nil {\n\t\treturn nil\n\t}\n\tif err := MkdirAll(b.system, b.path.Dir(), fs.ModePerm); err != nil {\n\t\treturn err\n\t}\n\tswitch db, err := bbolt.Open(b.path.String(), 0o600, &b.options); {\n\tcase errors.Is(err, syscall.EINVAL):\n\t\t// Assume that any EINVAL error is because flock(2) failed.\n\t\treturn fmt.Errorf(\"open %s: failed to acquire lock: %w\", b.path, err)\n\tcase err != nil:\n\t\treturn fmt.Errorf(\"open %s: %w\", b.path, err)\n\tdefault:\n\t\tb.empty = false\n\t\tb.db = db\n\t\treturn nil\n\t}\n}\n","sourceCodeStart":218,"sourceCodeEnd":245,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/boltpersistentstate.go#L218-L245","documentation":"open in boltpersistentstate.go:236 opens the bbolt state database with flock-based locking. On syscall.EINVAL it assumes flock(2) failed and wraps the error as \"open %s: failed to acquire lock\", indicating the lock could not be acquired on the state database file.","triggerScenarios":"Calling any persistent state method (Data, Get, Delete, DeleteBucket, ForEach, CopyTo) that triggers open while bbolt.Open returns EINVAL, typically from a filesystem that does not support flock.","commonSituations":"Persistent state (chezmoistate.boltdb) stored on network filesystems (NFS, SMB, CIFS) or filesystems without flock support; containers mounting state dirs from unsupported volumes; two processes contending on unsupported locking.","solutions":["Move the chezmoi state directory to a local filesystem (set CHEZMOI state dir / use default ~/.config/chezmoi).","If on NFS/SMB, remount with local locking enabled or switch to local storage.","Check for stale locks/other chezmoi processes holding the file; stop them and retry.","Verify kernel/filesystem support for flock on the mount (e.g. avoid tmpfs quirks in restricted containers)."],"exampleFix":"# before: state on NFS mount\nexport CHEZMOI_HOME=/mnt/nfs/chezmoi\n# after\nunset CHEZMOI_HOME  # use default local ~/.config/chezmoi","handlingStrategy":"try-catch","validationCode":"// Ensure state dir is on a filesystem supporting flock\nst, err := os.Stat(stateDir)\nif err != nil { return err }\n// e.g. reject known network mounts\nif strings.HasPrefix(mntType(stateDir), \"nfs\") {\n    return fmt.Errorf(\"state dir must be on a local filesystem\")\n}","typeGuard":null,"tryCatchPattern":"if err := state.Get(key, &v); err != nil {\n    if strings.Contains(err.Error(), \"failed to acquire lock\") {\n        // move state to local fs, clear stale lock, retry once\n    }\n    return err\n}","preventionTips":["Keep chezmoistate.boltdb on a local filesystem, never NFS/SMB.","Avoid running concurrent chezmoi processes against the same state.","Check mount options for flock support in containers.","Run `chezmoi doctor` to surface state path issues."],"tags":["locking","bolt","filesystem","flock"],"backgroundTag":"flock-unsupported-filesystem","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}