{"record":{"id":"9c4e5c00dc9c5136","repo":"larksuite/cli","slug":"busdiscover-mkdir-s-w","errorCode":null,"errorMessage":"busdiscover: mkdir %s: %w","messagePattern":"busdiscover: mkdir (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/event/adapter/localbus/busdiscover/pidfile.go","lineNumber":41,"sourceCode":"\n// Handle keeps the lifetime lock fd alive; OS releases on process exit.\ntype Handle struct {\n\tlock *lockfile.LockFile\n}\n\n// Release is for tests only; production lets process exit release the lock.\nfunc (h *Handle) Release() error {\n\tif h == nil || h.lock == nil {\n\t\treturn nil\n\t}\n\treturn h.lock.Unlock()\n}\n\n// WritePIDFile takes the alive lock and atomically writes pid + RFC3339 start time.\n// Returns lockfile.ErrHeld if another bus holds the lock.\nfunc 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","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/event/adapter/localbus/busdiscover/pidfile.go#L23-L59","documentation":"WritePIDFile wraps the failure of vfs.MkdirAll when creating the per-app events directory (mode 0700). The library throws it before taking the alive lock because it cannot guarantee a location to place bus.alive.lock and bus.pid. The wrapped underlying cause (permissions, path issues, filesystem errors) is preserved via %w.","triggerScenarios":"Calling WritePIDFile(eventsDir, pid) where eventsDir's path cannot be created: parent directory does not exist and cannot be created, a non-directory file exists at a path component, or permission denies creation.","commonSituations":"LARKSUITE_CLI_CONFIG_DIR or state dir pointing at a read-only mount, a stale regular file occupying the eventsDir path, running under a different user after a sudo-based install, or disk-full/EDQUOT on the state volume.","solutions":["Check the wrapped cause with errors.Is/As to identify the OS error (EACCES, ENOTDIR, ENOSPC) and fix the filesystem condition","Verify the parent of eventsDir exists and is writable by the current user; create or correct the config/state dir path","Remove or rename any regular file that occupies the eventsDir path so a directory can be created","Re-run with a writable alternate state directory (e.g. a fresh LARKSUITE_CLI_CONFIG_DIR) to confirm it is an environment issue"],"exampleFix":"// before: writing into a read-only or nonexistent state root\nerr := busdiscover.WritePIDFile(\"/var/lib/lark/events\", os.Getpid())\n// after: ensure the parent state dir exists and is writable first\nif err := os.MkdirAll(stateRoot, 0700); err != nil { return err }\nerr := busdiscover.WritePIDFile(filepath.Join(stateRoot, \"events\"), os.Getpid())","handlingStrategy":"validation","validationCode":"// Ensure the eventsDir parent exists and is writable before calling WritePIDFile\nparent := filepath.Dir(eventsDir)\nif info, err := os.Stat(parent); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"state dir %s missing\", parent)\n}\nif f, err := os.CreateTemp(parent, \".probe\"); err != nil {\n    return fmt.Errorf(\"state dir %s not writable: %w\", parent, err)\n} else { name := f.Name(); f.Close(); os.Remove(name) }","typeGuard":null,"tryCatchPattern":"h, err := busdiscover.WritePIDFile(eventsDir, pid)\nif err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) && (errors.Is(perr.Err, syscall.EACCES) || errors.Is(perr.Err, syscall.ENOSPC)) {\n        // fix environment: permissions or disk space, then retry\n    }\n    return err\n}","preventionTips":["Provision the CLI state/config directory with correct ownership before launching the bus","Do not point the state dir at read-only mounts, network shares, or tmpfs cleared on reboot","Avoid creating regular files where the eventsDir directory should live","Monitor disk space and quota on the volume hosting the state directory"],"tags":["go","filesystem","mkdir","pidfile","localbus"],"backgroundTag":"mkdir-permission-denied","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"}