gastownhall/beads · error
cannot start dolt server on port %d: %w
Error message
cannot start dolt server on port %d: %w
What it means
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'.
Source
Thrown at internal/doltserver/doltserver.go:1361
// Open log file
logFile, err := os.OpenFile(logPath(beadsDir), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) //nolint:gosec // G304: logPath derives from user-configured beadsDir
if err != nil {
return nil, fmt.Errorf("opening log file: %w", err)
}
// Resolve the port to use. Explicit ports (env/config) go through
// reclaimPort for conflict detection. Port 0 means ephemeral — allocate
// a fresh port from the OS with retry for TOCTOU races.
actualPort = cfg.Port
explicitPort := actualPort > 0
if explicitPort {
// Explicit port: check for conflicts and adopt existing servers.
adoptPID, reclaimErr := reclaimPort(cfg.Host, actualPort, beadsDir)
if reclaimErr != nil {
_ = logFile.Close()
return nil, fmt.Errorf("cannot start dolt server on port %d: %w", actualPort, reclaimErr)
}
if adoptPID > 0 {
_ = logFile.Close()
_ = os.WriteFile(pidPath(beadsDir), []byte(strconv.Itoa(adoptPID)), 0600)
_ = writePortFile(beadsDir, actualPort)
return &State{Running: true, PID: adoptPID, Port: actualPort, DataDir: doltDir}, nil
}
}
// Start dolt sql-server, with retry loop for ephemeral port TOCTOU.
pid = 0
lastErr = nil
attempts = 1
if !explicitPort {
attempts = maxEphemeralPortAttempts
}
for i := range attempts {View on GitHub (pinned to 71377f2769)
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).
Example fix
// before: port 4141 held by a stale process ss -ltnp | grep 4141 kill <pid> // after: bd starts cleanly, or set BD_PORT=0 for an ephemeral port
Defensive patterns
Strategy: try-catch
Validate before calling
// probe the explicit port before starting
const { createServer } = require('net');
const s = createServer();
s.once('error', e => console.error('port in use:', e.code));
s.listen(port, host, () => { s.close(); }); Type guard
null
Try / catch
try {
await bdStart();
} catch (e) {
const m = e.message.match(/cannot start dolt server on port (\d+)/);
if (m) { /* free the port or pick another, then retry */ }
throw e;
} Prevention
- 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.
When it happens
Trigger: Explicit port configured (env/config, not port 0) and reclaimPort fails while probing/reclaiming that port.
Common situations: 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.
Related errors
- dolt sql-server exited immediately on port %d (attempt %d/%d
- multiple .doltcfg directories detected
- pidfile: invalid port
- errStartInterrupted
- database server not running
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e3e14981537af79a.
Report an issue: GitHub.