{"record":{"id":"7ba35e5e24670f56","repo":"gastownhall/beads","slug":"write-pid-file-w","errorCode":null,"errorMessage":"write pid file: %w","messagePattern":"write pid file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/server.go","lineNumber":328,"sourceCode":"\t\t_ = stopBackendBounded(p.server)\n\t\treturn fmt.Errorf(\"re-check proxy stop epoch before publish: %w\", err)\n\t} else if changed {\n\t\treturn abortInterruptedStart()\n\t}\n\n\tif err := pidfile.Write(p.rootDir, PIDFileName, pidfile.PidFile{\n\t\tPid:         os.Getpid(),\n\t\tPort:        dataPort.Port,\n\t\tUpstreamID:  upstreamID,\n\t\tSchema:      pidfile.SchemaV2,\n\t\tKind:        pidfile.KindProxy,\n\t\tBirth:       string(birth),\n\t\tRootID:      rootID,\n\t\tControlPort: control.Port(),\n\t}); err != nil {\n\t\tp.stats.IncBackendStop()\n\t\t_ = stopBackendBounded(p.server)\n\t\treturn fmt.Errorf(\"write pid file: %w\", err)\n\t}\n\tdefer func() { _ = pidfile.Remove(p.rootDir, PIDFileName) }()\n\n\tg, gctx := errgroup.WithContext(ctx)\n\tg.Go(func() error {\n\t\t<-gctx.Done()\n\t\t_ = p.listener.Close()\n\t\t_ = control.Close()\n\t\treturn nil\n\t})\n\tg.Go(func() error { return p.idleWatcher(gctx) })\n\tg.Go(func() error { return p.acceptLoop(gctx) })\n\n\trunErr := g.Wait()\n\t_ = p.conns.Wait()\n\tp.stats.IncBackendStop()\n\tstopErr := stopBackendBounded(p.server)\n\tif stopErr != nil {","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/server.go#L310-L346","documentation":"ListenAndServe fails during final startup publishing when pidfile.Write cannot persist proxy.pid (the record pointing clients at the proxy's data port, control port, and identity). Before returning, the proxy rolls back: the backend is stopped and the backend-stop stat is incremented, so the start aborts cleanly rather than publishing a half-started proxy. This is a filesystem error wrapped with a stable 'write pid file' prefix.","triggerScenarios":"Calling the proxy start (ListenAndServe) when writing <rootDir>/proxy.pid fails: unwritable or read-only rootDir, disk full, rootDir deleted mid-start, path is a directory or has wrong permissions, or an immutable/ACL-blocked file at that path.","commonSituations":"Running bd under a user without write access to the workspace; a full tmpfs/quotad disk on CI; NFS/EACCES issues; a stale directory sitting where proxy.pid belongs; container with a read-only mount of the repo root.","solutions":["Check that rootDir exists, is a directory, and is writable by the current user (ls -ld <rootDir>; touch <rootDir>/.wtest).","Free disk space or raise the quota if the filesystem is full (df -h <rootDir>).","Remove any stray non-regular file named proxy.pid in rootDir and retry the start.","Fix mount permissions (chmod/chown, remount rw) or point bd at a writable rootDir.","Retry the start; if persistent, inspect the wrapped cause after 'write pid file: ' for the exact syscall error."],"exampleFix":"// before (shell): start on a read-only checkout\nbd dolt start   # write pid file: open /repo/.beads/proxy.pid: read-only file system\n// after\nmount -o remount,rw /repo   # or run bd from a writable workspace\nbd dolt start","handlingStrategy":"validation","validationCode":"info, err := os.Stat(rootDir)\nif err != nil || !info.IsDir() {\n    return fmt.Errorf(\"rootDir %s missing or not a directory\", rootDir)\n}\nif f, err := os.CreateTemp(rootDir, \".wtest*\"); err != nil {\n    return fmt.Errorf(\"rootDir %s not writable: %w\", rootDir, err)\n} else {\n    f.Close(); os.Remove(f.Name())\n}","typeGuard":null,"tryCatchPattern":"if err := proxy.ListenAndServe(ctx, ...); err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && strings.Contains(err.Error(), \"write pid file\") {\n        // rollback already done by the proxy; surface rootDir permission/space issue\n    }\n    return err\n}","preventionTips":["Ensure the bd workspace rootDir is writable by the service user before starting","Monitor free disk space where workspaces live","Do not run starts on read-only mounts; keep control files on a writable volume","Clean stray proxy.pid directories/files before start"],"tags":["go","filesystem","startup","pidfile"],"backgroundTag":"pidfile-write-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}