{"record":{"id":"aa60a775086a4dac","repo":"gastownhall/beads","slug":"port-d-is-busy-but-cannot-identify-the-process-n","errorCode":null,"errorMessage":"port %d is busy but cannot identify the process.\\n\\nCheck with: %s","messagePattern":"port (.+?) is busy but cannot identify the process\\.\\\\n\\\\nCheck with: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":430,"sourceCode":"//\n// Returns (adoptPID, nil) when an existing server should be adopted.\n// Returns (0, nil) when the port is free for a new server.\n// Returns (0, err) when the port can't be used.\nfunc reclaimPort(host string, port int, beadsDir string) (adoptPID int, err error) {\n\tif isPortAvailable(host, port) {\n\t\treturn 0, nil // port is free\n\t}\n\n\t// Port is busy — find out what's using it\n\tpid := findPIDOnPort(port)\n\tif pid == 0 {\n\t\t// Can't identify the process; port may be in TIME_WAIT or transient use.\n\t\t// Wait briefly and retry.\n\t\ttime.Sleep(2 * time.Second)\n\t\tif isPortAvailable(host, port) {\n\t\t\treturn 0, nil\n\t\t}\n\t\treturn 0, fmt.Errorf(\"port %d is busy but cannot identify the process.\\n\\nCheck with: %s\", port, fmt.Sprintf(portConflictHint, port))\n\t}\n\n\t// Check if it's a dolt sql-server process\n\tif !isDoltProcess(pid) {\n\t\treturn 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))\n\t}\n\n\t// It's a dolt process. Check if it's one we should adopt.\n\n\t// Check if the process is using our data directory (CWD matches our dolt dir).\n\t// dolt sql-server is started with cmd.Dir = doltDir, so CWD is the data dir.\n\tdoltDir := ResolveDoltDir(beadsDir)\n\tif isProcessInDir(pid, doltDir) {\n\t\treturn pid, nil // our server — adopt it\n\t}\n\n\t// Another beads project's Dolt server is on this port.\n\treturn 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))","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L412-L448","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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>"],"exampleFix":"// before: fixed port collides with a TIME_WAIT socket\nport := 8001\n// after: let bd pick an ephemeral port by clearing the explicit port config\n// bd dolt set port 0  (or remove the port from config.yaml)\n","handlingStrategy":"retry","validationCode":"// Check port availability before starting\nimport \"net\"\nfunc portFree(host string, port int) bool {\n    ln, err := net.Listen(\"tcp\", net.JoinHostPort(host, strconv.Itoa(port)))\n    if err != nil { return false }\n    ln.Close()\n    return true\n}","typeGuard":null,"tryCatchPattern":"_, err := doltserver.Start(beadsDir)\nif err != nil && strings.Contains(err.Error(), \"cannot identify the process\") {\n    time.Sleep(5 * time.Second) // allow TIME_WAIT to clear\n    _, err = doltserver.Start(beadsDir)\n}","preventionTips":["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"],"tags":["network","port-conflict","time-wait","dolt"],"backgroundTag":"port-already-in-use","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}