{"record":{"id":"299b74025c4d3514","repo":"larksuite/cli","slug":"busdiscover-rename-pid-file-w","errorCode":null,"errorMessage":"busdiscover: rename pid file: %w","messagePattern":"busdiscover: rename pid file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/event/adapter/localbus/busdiscover/pidfile.go","lineNumber":57,"sourceCode":"func WritePIDFile(eventsDir string, pid int) (*Handle, error) {\n\tif err := vfs.MkdirAll(eventsDir, 0700); err != nil {\n\t\treturn nil, fmt.Errorf(\"busdiscover: mkdir %s: %w\", eventsDir, err)\n\t}\n\tlock := lockfile.New(filepath.Join(eventsDir, aliveLockFileName))\n\tif err := lock.TryLock(); err != nil {\n\t\treturn nil, err\n\t}\n\tpidPath := filepath.Join(eventsDir, pidFileName)\n\ttmpPath := pidPath + \".tmp\"\n\tpayload := fmt.Sprintf(\"%d\\n%s\\n\", pid, time.Now().UTC().Format(time.RFC3339))\n\tif err := vfs.WriteFile(tmpPath, []byte(payload), 0600); err != nil {\n\t\t_ = lock.Unlock()\n\t\treturn nil, fmt.Errorf(\"busdiscover: write pid tmp: %w\", err)\n\t}\n\tif err := vfs.Rename(tmpPath, pidPath); err != nil {\n\t\t_ = vfs.Remove(tmpPath)\n\t\t_ = lock.Unlock()\n\t\treturn nil, fmt.Errorf(\"busdiscover: rename pid file: %w\", err)\n\t}\n\treturn &Handle{lock: lock}, nil\n}\n\nfunc readPIDFile(eventsDir string) (int, time.Time, error) {\n\tpidPath := filepath.Join(eventsDir, pidFileName)\n\tdata, err := vfs.ReadFile(pidPath)\n\tif err != nil {\n\t\treturn 0, time.Time{}, err\n\t}\n\tlines := strings.SplitN(strings.TrimSpace(string(data)), \"\\n\", 2)\n\tif len(lines) < 2 {\n\t\treturn 0, time.Time{}, fmt.Errorf(\"busdiscover: malformed pid file %s\", pidPath)\n\t}\n\tpid, err := strconv.Atoi(strings.TrimSpace(lines[0]))\n\tif err != nil {\n\t\treturn 0, time.Time{}, fmt.Errorf(\"busdiscover: malformed pid in %s: %w\", pidPath, err)\n\t}","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/event/adapter/localbus/busdiscover/pidfile.go#L39-L75","documentation":"WritePIDFile wraps the failure of vfs.Rename when atomically moving bus.pid.tmp over bus.pid. It cleans up the leftover tmp file and releases the alive lock before returning. The rename is what makes the pid file publish atomic; its failure means no pid file was updated.","triggerScenarios":"Calling WritePIDFile where the tmp-to-final rename fails: bus.pid exists as a directory, cross-device rename (tmp and target on different filesystems via unusual mounts), or target path became unwritable between mkdir and rename.","commonSituations":"A directory named bus.pid left behind by an odd tool or manual mistake, an overlay/odd mount splitting the dir, or an external watcher replacing the eventsDir contents concurrently.","solutions":["Check whether a directory or special file named bus.pid exists in eventsDir and remove/rename it","Inspect the wrapped OS error; EXDEV or EINVAL indicates unusual mounts — keep eventsDir on one normal filesystem","Verify no external process is replacing or locking files inside eventsDir during startup","Retry WritePIDFile; the lock was released so another attempt is safe"],"exampleFix":"// before: stale directory blocks the atomic rename\n// busdiscover: rename pid file: rename .../bus.pid.tmp .../bus.pid: is a directory\n$ find ~/.larkcli/events -name bus.pid -type d -exec rm -rf {} +\n// after: WritePIDFile(eventsDir, pid) succeeds","handlingStrategy":"validation","validationCode":"// Ensure the target pid path is not occupied by a non-regular file before WritePIDFile\npidPath := filepath.Join(eventsDir, \"bus.pid\")\nif info, err := os.Lstat(pidPath); err == nil && !info.Mode().IsRegular() {\n    return fmt.Errorf(\"%s is %v, not a regular file; remove it first\", pidPath, info.Mode())\n}","typeGuard":null,"tryCatchPattern":"h, err := busdiscover.WritePIDFile(eventsDir, pid)\nif err != nil && strings.Contains(err.Error(), \"rename pid file\") {\n    // clean any directory/special file at bus.pid, then retry once\n    if info, statErr := os.Lstat(filepath.Join(eventsDir, \"bus.pid\")); statErr == nil && !info.Mode().IsRegular() {\n        os.RemoveAll(filepath.Join(eventsDir, \"bus.pid\"))\n        h, err = busdiscover.WritePIDFile(eventsDir, pid)\n    }\n}","preventionTips":["Never manually create directories or symlinks named bus.pid in the events dir","Keep the whole events directory on a single normal filesystem so rename is not cross-device","Stop external watchers/sync tools from replacing files inside the events dir while the bus starts","Check the wrapped OS error (EXDEV/EISDIR/ENOTDIR) to pinpoint the rename blocker"],"tags":["go","filesystem","rename","pidfile","localbus"],"backgroundTag":"file-rename-failed","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}