{"record":{"id":"b9a7eab2a6e09b1b","repo":"windmill-labs/windmill","slug":"port-requested-is-already-in-use-holderhint-b9a7ea","errorCode":null,"errorMessage":"Port ${requested} is already in use${holderHint}. Using port ${port} instead.","messagePattern":"Port (.+?) is already in use(.+?)\\. Using port (.+?) instead\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cli/src/commands/pipeline/dev.ts","lineNumber":201,"sourceCode":"  watcher.on(\"change\", (_ev, filename) => {\n    if (filename && filename.toString().endsWith(\".lock\")) return;\n    if (timer) clearTimeout(timer);\n    timer = setTimeout(async () => {\n      timer = undefined;\n      try {\n        current = await buildBundle();\n        log.info(colors.cyan(`↻ rebuilt graph (${current.scripts.length} scripts)`));\n        broadcast();\n      } catch (e: any) {\n        log.error(colors.red(`Failed to rebuild pipeline graph: ${e.message}`));\n      }\n    }, 150);\n  });\n  watcher.on(\"error\", (e) => log.error(colors.red(`Watcher error: ${e.message}`)));\n\n  const port = await resolveBindPort(opts.port ?? PORT, \"wmill pipeline dev\", {\n    info: (m) => log.info(m),\n    warn: (m) => log.warn(m),\n  });\n\n  const server = http.createServer((_req, res) => {\n    res.writeHead(200);\n    res.end();\n  });\n  // Loopback bind keeps the LAN out, but any browser tab can still open a\n  // `ws://localhost:<port>` connection — and each frame ships the folder's full\n  // script source. Gate the upgrade on an unguessable per-session token (carried\n  // in the dev-page URL) so a stray page on the predictable dev port can't\n  // exfiltrate the source. base64url → safe as a query value.\n  // Stable across restarts (scoped to remote+workspace+root+folder+port) so an\n  // already-open page reconnects after a CLI restart (see stableWsToken), not\n  // just after a transient WS drop.\n  const wsToken = await stableWsToken(\n    workspace.remote,\n    workspace.workspaceId,\n    root,","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/pipeline/dev.ts#L183-L219","documentation":"This is a warning (not a thrown error) emitted by `wmill pipeline dev` in cli/src/commands/pipeline/dev.ts. When the requested port is already bound, resolveBindPort picks the next free port and logs which port was requested, who held it (holderHint), and which port is actually used. It exists so the dev server still starts instead of failing with EADDRINUSE.","triggerScenarios":"Running `wmill pipeline dev` (optionally with --port) while another process — often a previous `wmill pipeline dev` that never shut down, another wmill dev command, or any dev server — is already listening on the requested port (default PORT constant).","commonSituations":"A stale pipeline dev server left running in another terminal; two worktrees running dev servers simultaneously; a crashed session that didn't receive SIGINT; a hardcoded --port colliding with a dockerized service.","solutions":["Check the log line: it already tells you the port actually used — just open/use that port instead.","Find and stop the process holding the requested port (e.g. lsof -i :<port> or ss -ltnp) then rerun the command.","Pass an explicit free port with --port <n> to make the assignment deterministic.","If a stale `wmill pipeline dev` is the holder, kill it (it also holds the WebSocket the UI connects to)."],"exampleFix":"// before (deterministic port request that collides)\nwmill pipeline dev --port 4545\n// after\nlsof -ti :4545 | xargs kill   # free the port first\nwmill pipeline dev --port 4545","handlingStrategy":"validation","validationCode":"// check the port before invoking the command\nconst net = require('net');\nfunction portFree(port) {\n  return new Promise(res => {\n    const s = net.createServer();\n    s.once('error', () => res(false));\n    s.listen(port, () => s.close(() => res(true)));\n  });\n}\nif (!(await portFree(4545))) console.warn('port 4545 busy; pick another');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always read the actual assigned port from the command output rather than assuming the requested one.","Use --port with a known-free high port in scripts/CI.","Kill stale dev servers before rerunning (lsof -ti :<port> | xargs kill).","One dev server per worktree/terminal to avoid collisions."],"tags":["port-in-use","cli","dev-server","network"],"backgroundTag":"port-already-in-use","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}