gastownhall/beads · error
port %d is busy but cannot identify the process.\n\nCheck wi
Error message
port %d is busy but cannot identify the process.\n\nCheck with: %s
What it means
reclaimPort validates a user-configured (explicit) port before Start launches dolt sql-server. When the port is busy but findPIDOnPort returns 0 (the listener's process cannot be identified — common with TIME_WAIT sockets or other users' processes), it waits 2 seconds and retries; if still busy it throws this error because bd cannot decide whether the port is safe to reclaim.
Source
Thrown at internal/doltserver/doltserver.go:430
//
// Returns (adoptPID, nil) when an existing server should be adopted.
// Returns (0, nil) when the port is free for a new server.
// Returns (0, err) when the port can't be used.
func reclaimPort(host string, port int, beadsDir string) (adoptPID int, err error) {
if isPortAvailable(host, port) {
return 0, nil // port is free
}
// Port is busy — find out what's using it
pid := findPIDOnPort(port)
if pid == 0 {
// Can't identify the process; port may be in TIME_WAIT or transient use.
// Wait briefly and retry.
time.Sleep(2 * time.Second)
if isPortAvailable(host, port) {
return 0, nil
}
return 0, fmt.Errorf("port %d is busy but cannot identify the process.\n\nCheck with: %s", port, fmt.Sprintf(portConflictHint, port))
}
// Check if it's a dolt sql-server process
if !isDoltProcess(pid) {
return 0, fmt.Errorf("port %d is in use by a non-dolt process (PID %d).\n\n%s\n\nFree the port or configure a different one with: bd dolt set port <port>", port, pid, portConflictDiagnostics(port))
}
// It's a dolt process. Check if it's one we should adopt.
// Check if the process is using our data directory (CWD matches our dolt dir).
// dolt sql-server is started with cmd.Dir = doltDir, so CWD is the data dir.
doltDir := ResolveDoltDir(beadsDir)
if isProcessInDir(pid, doltDir) {
return pid, nil // our server — adopt it
}
// Another beads project's Dolt server is on this port.
return 0, fmt.Errorf("port %d is in use by another project's dolt server (PID %d).\n\n%s\n\nFree the port or use a different one with: bd dolt set port <port>", port, pid, portConflictDiagnostics(port))View on GitHub (pinned to 71377f2769)
Solutions
- Run the diagnostics command in the message (platform-specific lsof/ss command) to find the listener
- Wait a few minutes for TIME_WAIT sockets to expire and retry bd
- Set SO_REUSEADDR-equivalent behavior by simply retrying bd start after a short delay
- If the listener is a foreign container/service, either stop it or point bd at it via BEADS_DOLT_SERVER_HOST/PORT instead of reclaiming
- Choose a different explicit port with: bd dolt set port <port>
Example fix
// before: fixed port collides with a TIME_WAIT socket port := 8001 // after: let bd pick an ephemeral port by clearing the explicit port config // bd dolt set port 0 (or remove the port from config.yaml)
Defensive patterns
Strategy: retry
Validate before calling
// Check port availability before starting
import "net"
func portFree(host string, port int) bool {
ln, err := net.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(port)))
if err != nil { return false }
ln.Close()
return true
} Try / catch
_, err := doltserver.Start(beadsDir)
if err != nil && strings.Contains(err.Error(), "cannot identify the process") {
time.Sleep(5 * time.Second) // allow TIME_WAIT to clear
_, err = doltserver.Start(beadsDir)
} Prevention
- Avoid immediately restarting bd after killing a server; wait for TIME_WAIT
- Prefer ephemeral ports over fixed explicit ports
- Run lsof -i :<port> to identify mysterious listeners before pinning a port
- Avoid NAT/container port mappings that hide the owning PID
When it happens
Trigger: Start() with an explicit port where isPortAvailable fails, no owning PID is discoverable (e.g. socket in TIME_WAIT, listener owned by another user/namespace), and the port remains unavailable after the 2-second retry.
Common situations: Restarting bd immediately after killing a previous server (TIME_WAIT lingering), Docker/NAT setups where the listener lives in another network namespace, containers where lsof/ss lack permission to map the port to a PID.
Related errors
- port %d is in use by a non-dolt process (PID %d).\n\n%s\n\nF
- port %d is in use by another project's dolt server (PID %d).
- dolt sql-server exited before listener became ready
- failed to remove backup: %w
- server not reachable: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/aa60a775086a4dac.
Report an issue: GitHub.