{"record":{"id":"e3e14981537af79a","repo":"gastownhall/beads","slug":"cannot-start-dolt-server-on-port-d-w","errorCode":null,"errorMessage":"cannot start dolt server on port %d: %w","messagePattern":"cannot start dolt server on port (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":1361,"sourceCode":"\n\t\t// Open log file\n\t\tlogFile, err := os.OpenFile(logPath(beadsDir), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) //nolint:gosec // G304: logPath derives from user-configured beadsDir\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"opening log file: %w\", err)\n\t\t}\n\n\t\t// Resolve the port to use. Explicit ports (env/config) go through\n\t\t// reclaimPort for conflict detection. Port 0 means ephemeral — allocate\n\t\t// a fresh port from the OS with retry for TOCTOU races.\n\t\tactualPort = cfg.Port\n\t\texplicitPort := actualPort > 0\n\n\t\tif explicitPort {\n\t\t\t// Explicit port: check for conflicts and adopt existing servers.\n\t\t\tadoptPID, reclaimErr := reclaimPort(cfg.Host, actualPort, beadsDir)\n\t\t\tif reclaimErr != nil {\n\t\t\t\t_ = logFile.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"cannot start dolt server on port %d: %w\", actualPort, reclaimErr)\n\t\t\t}\n\t\t\tif adoptPID > 0 {\n\t\t\t\t_ = logFile.Close()\n\t\t\t\t_ = os.WriteFile(pidPath(beadsDir), []byte(strconv.Itoa(adoptPID)), 0600)\n\t\t\t\t_ = writePortFile(beadsDir, actualPort)\n\t\t\t\treturn &State{Running: true, PID: adoptPID, Port: actualPort, DataDir: doltDir}, nil\n\t\t\t}\n\t\t}\n\n\t\t// Start dolt sql-server, with retry loop for ephemeral port TOCTOU.\n\t\tpid = 0\n\t\tlastErr = nil\n\t\tattempts = 1\n\t\tif !explicitPort {\n\t\t\tattempts = maxEphemeralPortAttempts\n\t\t}\n\n\t\tfor i := range attempts {","sourceCodeStart":1343,"sourceCodeEnd":1379,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L1343-L1379","documentation":"For an explicit (non-ephemeral) port, Start() calls reclaimPort(host, port, beadsDir) to detect conflicts and adopt an already-running server on that port. If reclaimPort returns an error, the log file is closed and Start fails with 'cannot start dolt server on port %d'.","triggerScenarios":"Explicit port configured (env/config, not port 0) and reclaimPort fails while probing/reclaiming that port.","commonSituations":"Port held by a foreign process that cannot be adopted; stale PID/port files pointing at unrelated processes; permission errors inspecting /proc or lsof; another app bound to the configured port.","solutions":["Find what holds the port (lsof -i :PORT or ss -ltnp) and stop the conflicting process if it is safe.","If it is another bd/dolt instance on this data dir, remove stale PID/port files in the beads dir and retry.","Change the configured port to a free one in beads config or the environment variable.","Verify reclaimPort's OS probes can run (permissions for lsof/ps, /proc access in containers)."],"exampleFix":"// before: port 4141 held by a stale process\nss -ltnp | grep 4141\nkill <pid>\n// after: bd starts cleanly, or set BD_PORT=0 for an ephemeral port","handlingStrategy":"try-catch","validationCode":"// probe the explicit port before starting\nconst { createServer } = require('net');\nconst s = createServer();\ns.once('error', e => console.error('port in use:', e.code));\ns.listen(port, host, () => { s.close(); });","typeGuard":"null","tryCatchPattern":"try {\n  await bdStart();\n} catch (e) {\n  const m = e.message.match(/cannot start dolt server on port (\\d+)/);\n  if (m) { /* free the port or pick another, then retry */ }\n  throw e;\n}","preventionTips":["Prefer port 0 (ephemeral) unless the port must be fixed.","Don't reuse the same port for multiple data dirs.","Clean stale PID/port files after crashes.","Document reserved ports for shared hosts."],"tags":["port","startup","conflict"],"backgroundTag":"port-conflict","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}