{"record":{"id":"fec97f565877e77f","repo":"gastownhall/beads","slug":"reading-pid-file-w","errorCode":null,"errorMessage":"reading PID file: %w","messagePattern":"reading PID file: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":876,"sourceCode":"\t\t\tif cfg.Port == 0 {\n\t\t\t\tcfg.Port = configfile.DefaultDoltServerPort\n\t\t\t\tcfg.PortSource = PortSourceExternalHostDefault\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cfg\n}\n\n// IsRunning checks if a managed server is running for this beadsDir.\n// Returns a State with Running=true if a valid dolt process is found.\nfunc IsRunning(beadsDir string) (*State, error) {\n\tdata, err := os.ReadFile(pidPath(beadsDir))\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn &State{Running: false}, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"reading PID file: %w\", err)\n\t}\n\n\tpid, err := strconv.Atoi(strings.TrimSpace(string(data)))\n\tif err != nil {\n\t\t// Corrupt PID file implies stale state; clear the port file too.\n\t\t_ = os.Remove(pidPath(beadsDir))\n\t\t_ = os.Remove(portPath(beadsDir))\n\t\treturn &State{Running: false}, nil\n\t}\n\n\t// Check if process is alive\n\tif !isProcessAlive(pid) {\n\t\t// Process is dead — clear all tracked state for this server.\n\t\t_ = os.Remove(pidPath(beadsDir))\n\t\t_ = os.Remove(portPath(beadsDir))\n\t\treturn &State{Running: false}, nil\n\t}\n","sourceCodeStart":858,"sourceCodeEnd":894,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L858-L894","documentation":"IsRunning reads the bd PID file for the given beads dir to report server state. If os.ReadFile fails with anything other than NotExist (permission denied, is-a-directory, I/O error), the read error is wrapped as this error. A missing PID file is normal (returns Running:false); an unreadable one is not.","triggerScenarios":"Calling IsRunning(beadsDir) (directly or via EnsureRunningDetailed/Start/StopWithForce) when pidPath(beadsDir) exists but cannot be read — permission changed, path is a directory, or an I/O error occurs.","commonSituations":"The PID file was created by another user (e.g. bd once run under sudo) so the current user can't read it, a directory named like the PID file after a botched restore, or .beads on a failing mount.","solutions":["Inspect the wrapped OS error for the exact cause","Fix ownership of the .beads directory (avoid running bd with sudo): chown -R $(whoami) .beads","If the PID file is a directory or corrupt, remove it — bd treats it as stale state","Check the mount/filesystem health of the .beads directory"],"exampleFix":"// before: running bd as root creates root-owned files in .beads\nsudo bd dolt start\n// after: run bd as your own user; fix existing ownership\nchown -R $(whoami) .beads\nbd dolt start","handlingStrategy":"try-catch","validationCode":"pidFile := filepath.Join(beadsDir, \"daemon.pid\")\nif fi, err := os.Stat(pidFile); err == nil && fi.IsDir() {\n    return fmt.Errorf(\"%s is a directory; remove it\", pidFile)\n}","typeGuard":"func isPIDFileReadErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"reading PID file\")\n}","tryCatchPattern":"state, err := doltserver.IsRunning(beadsDir)\nif err != nil {\n    if strings.Contains(err.Error(), \"permission denied\") {\n        // repair ownership, then retry\n        exec.Command(\"chown\", \"-R\", os.Getenv(\"USER\"), beadsDir).Run()\n        state, err = doltserver.IsRunning(beadsDir)\n    }\n    if err != nil { return err }\n}","preventionTips":["Avoid running bd with sudo — it creates root-owned files in .beads","Do not restore .beads from archives that mangle file types/permissions","Monitor the health of the filesystem/mount hosting .beads","If a PID file is corrupt, remove it; bd treats missing as not-running"],"tags":["filesystem","pid-file","permissions","dolt"],"backgroundTag":"file-read-permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}