{"record":{"id":"1eb3716d3c6478d2","repo":"gastownhall/beads","slug":"writing-port-file-w","errorCode":null,"errorMessage":"writing port file: %w","messagePattern":"writing port file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":1492,"sourceCode":"\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"failed to start dolt server after %d attempts: %w\\nCheck logs: %s\",\n\t\t\t\tattempts, lastErr, logPath(beadsDir))\n\t\t}\n\t}\n\n\t// Write PID and port files\n\tif err := os.WriteFile(pidPath(beadsDir), []byte(strconv.Itoa(pid)), 0600); err != nil {\n\t\tif proc, findErr := os.FindProcess(pid); findErr == nil {\n\t\t\t_ = proc.Kill()\n\t\t}\n\t\treturn nil, fmt.Errorf(\"writing PID file: %w\", err)\n\t}\n\tif err := writePortFile(beadsDir, actualPort); err != nil {\n\t\tif proc, findErr := os.FindProcess(pid); findErr == nil {\n\t\t\t_ = proc.Kill()\n\t\t}\n\t\t_ = os.Remove(pidPath(beadsDir))\n\t\treturn nil, fmt.Errorf(\"writing port file: %w\", err)\n\t}\n\n\t// Wait for server to accept connections\n\tif err := waitForReady(cfg.Host, actualPort, readyTimeout()); err != nil {\n\t\tif proc, findErr := os.FindProcess(pid); findErr == nil {\n\t\t\t_ = proc.Kill()\n\t\t}\n\t\t_ = os.Remove(pidPath(beadsDir))\n\t\t_ = os.Remove(portPath(beadsDir))\n\t\tif hasJournalCorruption, logErr := logHasCorruptJournalError(logPath(beadsDir)); logErr == nil && hasJournalCorruption {\n\t\t\treturn nil, fmt.Errorf(\"server started (PID %d) but not accepting connections on port %d: %w\\n\\n%s\",\n\t\t\t\tpid, actualPort, err, corruptJournalRecoveryHint(beadsDir))\n\t\t}\n\t\treturn nil, fmt.Errorf(\"server started (PID %d) but not accepting connections on port %d: %w\\nCheck logs: %s\",\n\t\t\tpid, actualPort, err, logPath(beadsDir))\n\t}\n\n\treturn &State{","sourceCodeStart":1474,"sourceCodeEnd":1510,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L1474-L1510","documentation":"This error is returned by doltserver.Start after the dolt sql-server process was successfully spawned, but writing the port file (<beadsDir>/dolt-server.port) to disk failed. Because the port file is how other bd processes discover which port the server listens on, a failure here leaves the server useless, so Start kills the fresh process and removes the just-written PID file before wrapping the underlying os.WriteFile error with %w.","triggerScenarios":"writePortFile(beadsDir, actualPort) returns an error right after a successful server spawn — typically because the beads directory is read-only, was deleted mid-start, disk is full, an immutable/permission-locked file exists at the port path, or an OS-level I/O error occurs during os.WriteFile.","commonSituations":"Running bd in a container or CI workspace with a read-only or tmpfs-mounted beads dir; hitting a full disk after long unattended runs; the .beads directory being removed or permission-changed by another process while bd was starting; filesystem quota exhaustion; antivirus/EDR blocking writes to dot-directories.","solutions":["Check permissions and writability of the beads directory (ls -ld .beads) and ensure the current user can create files there","Free disk space and check inode/quota limits (df -h, df -i)","Remove any stale or immutable dolt-server.port file (rm -f .beads/dolt-server.port; chattr -i if needed)","If the directory is intentionally read-only, run bd against a writable beads dir or relocate BEADS_DIR","Retry bd; if persistent, inspect the wrapped error (%w) for the exact errno"],"exampleFix":"// before: start fails, server killed\n// $ bd doctor\n//   error: writing port file: open /repo/.beads/dolt-server.port: read-only file system\n// after: make the beads dir writable (or mount it writable)\n// $ mount -o remount,rw /repo\n// $ chmod u+w /repo/.beads","handlingStrategy":"validation","validationCode":"// Before starting, ensure the beads dir exists and is writable\ninfo, err := os.Stat(beadsDir)\nif err != nil || !info.IsDir() {\n    return fmt.Errorf(\"beads dir %s missing\", beadsDir)\n}\nprobe, perr := os.CreateTemp(beadsDir, \".write-probe*\")\nif perr != nil {\n    return fmt.Errorf(\"beads dir not writable: %w\", perr)\n}\nprobe.Close(); os.Remove(probe.Name())","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the beads directory on a writable, non-read-only volume in containers/CI","Monitor disk space and inodes on the volume hosting .beads","Never chmod/chattr or replace .beads while bd is starting","Confirm write access with bd doctor before automation runs"],"tags":["go","filesystem","server-startup","port-file"],"backgroundTag":"port-file-write-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}