{"record":{"id":"22e9c1992c367bac","repo":"can1357/oh-my-pi","slug":"port-host-chosen-is-already-in-use-cannot-s","errorCode":null,"errorMessage":"Port ${host}:${chosen} is already in use; cannot start remote debugger there.","messagePattern":"Port (.+?):(.+?) is already in use; cannot start remote debugger there\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/debug/remote-debugger.ts","lineNumber":123,"sourceCode":"export async function startRemoteDebuggerServer(options: StartRemoteDebuggerOptions = {}): Promise<RemoteDebuggerInfo> {\n\tif (active) return active;\n\tstarting ??= launch(options);\n\ttry {\n\t\treturn await starting;\n\t} finally {\n\t\tstarting = null;\n\t}\n}\n\nasync function launch({ port, start = startRemoteDebugger }: StartRemoteDebuggerOptions): Promise<RemoteDebuggerInfo> {\n\tconst host = DEFAULT_HOST;\n\tconst chosen = port ?? (await reserveFreePort(host));\n\n\t// Something already on this port? Refuse up front: otherwise Bun throws a\n\t// real bind error and our success probe would connect to that unrelated\n\t// service, marking a bogus endpoint as the debugger.\n\tif (await tryConnect(host, chosen, PROBE_INTERVAL_MS)) {\n\t\tthrow new Error(`Port ${host}:${chosen} is already in use; cannot start remote debugger there.`);\n\t}\n\n\tlet thrown: unknown;\n\ttry {\n\t\tstart(host, chosen);\n\t} catch (err) {\n\t\t// Bun's startRemoteDebugger throws a spurious bind error even on success,\n\t\t// so defer the verdict to the loopback probe below.\n\t\tthrown = err;\n\t}\n\n\tif (await waitForListening(host, chosen)) {\n\t\tactive = { host, port: chosen };\n\t\treturn active;\n\t}\n\n\tthrow thrown instanceof Error ? thrown : new Error(`Remote debugger socket never came up on ${host}:${chosen}`);\n}","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/debug/remote-debugger.ts#L105-L141","documentation":"startRemoteDebugger/launch refuses to bind its remote-debugger server when the chosen port already accepts connections. It probes the port first because a plain bind error would be ambiguous and a success probe might connect to an unrelated service already listening there.","triggerScenarios":"Calling launch/startRemoteDebuggerServer with an explicit `port` that another process is listening on, or when `reserveFreePort(host)` returned a port that got claimed between reservation and bind (TOCTOU), on the given host.","commonSituations":"Two omp/debugger instances started concurrently; a stale debugger server from a crashed previous run still holding the port; another dev service occupying the port; hardcoded port in config colliding across team members or containers.","solutions":["Omit the `port` argument so a free port is reserved automatically","Find and stop the process occupying the port (e.g. `lsof -i :<port>` / `ss -ltnp`)","Choose a different port in your configuration","Retry after a delay if the conflict was transient (another instance shutting down)"],"exampleFix":"// before\nconst dbg = await startRemoteDebuggerServer({ host: '127.0.0.1', port: 9229 });\n// after\nconst dbg = await startRemoteDebuggerServer({ host: '127.0.0.1' }); // picks a free port","handlingStrategy":"validation","validationCode":"import { tryConnect } from './remote-debugger';\nif (await tryConnect(host, port, 100)) {\n\tthrow new SkipOperation(`port ${host}:${port} occupied`);\n}","typeGuard":null,"tryCatchPattern":"try {\n\tconst dbg = await startRemoteDebuggerServer({ host, port });\n} catch (err) {\n\tif (err.message.includes('already in use')) {\n\t\tdbg = await startRemoteDebuggerServer({ host }); // let it pick a free port\n\t}\n}","preventionTips":["Prefer auto port selection over fixed ports","Clean up debugger servers on exit (SIGINT handlers)","Use unique port ranges per developer/container"],"tags":["network","port-conflict","debugger","bind"],"backgroundTag":"port-already-in-use","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}