{"record":{"id":"eceed34f8ef7032d","repo":"gastownhall/beads","slug":"port-d-is-in-use-by-another-project-s-dolt-server","errorCode":null,"errorMessage":"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>","messagePattern":"port (.+?) is in use by another project's dolt server \\(PID (.+?)\\)\\.\\\\n\\\\n(.+?)\\\\n\\\\nFree the port or use a different one with: bd dolt set port <port>","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/doltserver/doltserver.go","lineNumber":448,"sourceCode":"\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))\n}\n\n// portConflictDiagnostics returns a multi-line block of operator-actionable\n// hints for diagnosing what's holding a port. Combines the platform-specific\n// listener-discovery command with a docker-in-the-loop hint that frequently\n// applies in practice — operators running their own dolt sql-server in a\n// container don't realize bd would otherwise try to start a competing\n// instance and lose the race (GH#3516).\nfunc portConflictDiagnostics(port int) string {\n\treturn fmt.Sprintf(\"Identify the listener:\\n  %s\\n\\n\"+\n\t\t\"If the listener is YOUR own Dolt instance (e.g., a docker container \"+\n\t\t\"or systemd unit you manage), bd does not need to start a new server. \"+\n\t\t\"Configure bd to talk to the existing server instead:\\n\"+\n\t\t\"  export BEADS_DOLT_SERVER_HOST=<host>  # 127.0.0.1 for local container\\n\"+\n\t\t\"  export BEADS_DOLT_SERVER_PORT=%d\\n\"+\n\t\t\"  bd dolt status   # verify reachable\",\n\t\tfmt.Sprintf(portConflictHint, port), port)\n}","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/doltserver/doltserver.go#L430-L466","documentation":"When the explicit port is held by a dolt process, reclaimPort checks whether that process's working directory matches this project's dolt dir (ResolveDoltDir). If it belongs to a different beads project, bd refuses to kill it — it's another project's live server — and errors with the PID and diagnostics instead.","triggerScenarios":"Start() with an explicit port that is already bound by another beads project's dolt sql-server (a dolt process whose CWD is not this project's dolt data directory), so isProcessInDir(pid, doltDir) is false.","commonSituations":"Multiple bd checkouts sharing one fixed port in config.yaml or BEADS_DOLT_SERVER_PORT in the shell environment, where whichever project started first owns the port.","solutions":["Give each project its own port: bd dolt set port <unique-port> in the second project","Remove the fixed port (use shared-server mode) so projects share one server: ~/.beads/shared-server","Stop the other project's server (bd dolt stop in that project) if you no longer need it","Use BEADS_DOLT_SERVER_HOST/PORT to connect to the other server only if it serves the data you need"],"exampleFix":"// before: both projects pinned to the same port\n# project A and B both: bd dolt set port 31145\n// after: per-project ports\n# project A: bd dolt set port 31145\n# project B: bd dolt set port 31146","handlingStrategy":"validation","validationCode":"// Ensure the fixed port is unique per project before start\ncfgPort := 31145 // read from config\nout, _ := exec.Command(\"sh\", \"-c\", fmt.Sprintf(\"lsof -ti :%d | xargs -r ps -o cmd= -p\", cfgPort)).Output()\nif strings.Contains(string(out), \"dolt sql-server\") && !strings.Contains(string(out), os.Getenv(\"PWD\")) {\n    fmt.Println(\"port held by another project's dolt server; choose a different port\")\n}","typeGuard":null,"tryCatchPattern":"_, err := doltserver.Start(beadsDir)\nif err != nil && strings.Contains(err.Error(), \"another project's dolt server\") {\n    // reallocate this project to a unique port and retry\n    exec.Command(\"bd\", \"dolt\", \"set\", \"port\", \"31146\").Run()\n    _, err = doltserver.Start(beadsDir)\n}","preventionTips":["Give every project its own explicit port, or use shared-server mode instead","Never export a single BEADS_DOLT_SERVER_PORT globally across projects","Adopt shared-server mode (~/.beads/shared-server) for multi-project machines","Document each project's port allocation to avoid accidental reuse"],"tags":["network","port-conflict","dolt","multi-project"],"backgroundTag":"port-already-in-use","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}