{"record":{"id":"8a5eaf9ddffc850a","repo":"chenglou/pretext","slug":"timed-out-waiting-for-local-port-port","errorCode":null,"errorMessage":"Timed out waiting for local port ${port}","messagePattern":"Timed out waiting for local port (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/browser-automation.ts","lineNumber":93,"sourceCode":"  for (let i = 0; i < 200; i++) {\n    const open = await new Promise<boolean>(resolve => {\n      const socket = createConnection({ host: '127.0.0.1', port })\n      let settled = false\n\n      const finish = (value: boolean): void => {\n        if (settled) return\n        settled = true\n        socket.destroy()\n        resolve(value)\n      }\n\n      socket.once('connect', () => finish(true))\n      socket.once('error', () => finish(false))\n    })\n    if (open) return\n    await sleep(100)\n  }\n  throw new Error(`Timed out waiting for local port ${port}`)\n}\n\nexport async function getAvailablePort(requestedPort: number | null = null): Promise<number> {\n  if (requestedPort !== null && Number.isFinite(requestedPort) && requestedPort > 0) {\n    return requestedPort\n  }\n\n  return await new Promise((resolve, reject) => {\n    const server = createNetServer()\n    server.once('error', reject)\n    server.listen(0, '127.0.0.1', () => {\n      const address = server.address()\n      if (address === null || typeof address === 'string') {\n        reject(new Error('Failed to allocate a free port'))\n        return\n      }\n\n      const { port } = address","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/chenglou/pretext/blob/ac49b09b7d83ede19581fa94a8b892b07d309baf/scripts/browser-automation.ts#L75-L111","documentation":"Thrown by waitForPort() in browser-automation.ts after 200 failed TCP connection attempts (100ms apart = 20s) to 127.0.0.1:<port>. Unlike waitForServer (error 4) which does HTTP fetches, this opens a raw net socket and checks for 'connect' vs 'error'. It is used to wait for WebDriver/BiDi debugging ports (not HTTP servers), so an HTTP-unreachable but TCP-open port still counts as ready. If the target process never listens within 20s, it throws.","triggerScenarios":"The Firefox remote-debugging port (initializeFirefoxSession) never accepts connections within 20s — Firefox failed to launch, crashed on startup, or the port was wrong. Also any other caller of waitForPort whose target process did not bind in time.","commonSituations":"Firefox is not installed at the hardcoded /Applications/Firefox.app path; Firefox is already running and refusing --new-instance; the spawned profile is corrupted; macOS Gatekeeper quarantining the binary; heavy system load delaying Firefox startup beyond 20s.","solutions":["Confirm Firefox is installed at /Applications/Firefox.app/Contents/MacOS/firefox (the path is hardcoded at browser-automation.ts:360).","Quit any running Firefox instance before running the script (--new-instance requires no existing process).","Manually launch Firefox with the same flags to see the startup error.","Clear stale profile dirs under mkdtemp's tmpdir prefix 'pretext-firefox-'."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Confirm the Firefox binary exists before spawning.\nimport { existsSync } from 'node:fs'\nif (!existsSync('/Applications/Firefox.app/Contents/MacOS/firefox')) {\n  throw new Error('Firefox not found at /Applications/Firefox.app')\n}","typeGuard":null,"tryCatchPattern":"// Add a retry around waitForPort for transient startup races.\nasync function waitForPortWithRetry(port: number, attempts = 3): Promise<void> {\n  for (let i = 0; i < attempts; i++) {\n    try { await waitForPort(port); return }\n    catch { if (i === attempts - 1) throw }\n  }\n}","preventionTips":["Quit any running Firefox before launching the script (--new-instance needs exclusivity).","Ensure Firefox is installed at the hardcoded /Applications path.","Clear stale profile dirs with the 'pretext-firefox-' tmp prefix.","Run Firefox manually with the same flags to catch startup errors early."],"tags":["browser-automation","firefox","webdriver","network","timeout","tcp"],"backgroundTag":null,"analyzedSha":"ac49b09b7d83ede19581fa94a8b892b07d309baf","analyzedAt":"2026-08-12T17:03:16.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}