{"record":{"id":"19c93370a3272fc0","repo":"ruvnet/ruflo","slug":"websocket-transport-already-running-19c933","errorCode":null,"errorMessage":"WebSocket transport already running","messagePattern":"WebSocket transport already running","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/shared/src/mcp/transport/websocket.ts","lineNumber":92,"sourceCode":"  // Statistics\n  private messagesReceived = 0;\n  private messagesSent = 0;\n  private errors = 0;\n  private totalConnections = 0;\n\n  constructor(\n    private readonly logger: ILogger,\n    private readonly config: WebSocketTransportConfig\n  ) {\n    super();\n  }\n\n  /**\n   * Start the transport\n   */\n  async start(): Promise<void> {\n    if (this.running) {\n      throw new Error('WebSocket transport already running');\n    }\n\n    this.logger.info('Starting WebSocket transport', {\n      host: this.config.host,\n      port: this.config.port,\n      path: this.config.path || '/ws',\n    });\n\n    // Create HTTP server for WebSocket upgrade\n    this.server = createServer((req, res) => {\n      // Simple HTTP response for non-WebSocket requests\n      res.writeHead(426, { 'Content-Type': 'text/plain' });\n      res.end('Upgrade Required - WebSocket connection expected');\n    });\n\n    // Create WebSocket server\n    this.wss = new WebSocketServer({\n      server: this.server,","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/shared/src/mcp/transport/websocket.ts#L74-L110","documentation":"WebSocketTransport.start() creates an HTTP server for the WebSocket upgrade (answering 426 to non-WS requests) and binds host, port and path (default '/ws'); it is guarded by a running flag. A second start() on the same instance throws because the port/path are already bound and client bookkeeping is live. stop() releases the server and resets the flag.","triggerScenarios":"Calling start() twice; reconnect/reload logic reusing the transport without stop(); two modules sharing one WebSocketTransport instance both starting it; retry wrapper around start() firing after a slow first success.","commonSituations":"Config reload paths that rebuild wiring but keep the transport object; test harnesses sharing a module-level transport; supervisors that 'ensure started' by calling start() unconditionally.","solutions":["Memoize: startPromise ??= transport.start()","Restart properly: await transport.stop() then start()","Otherwise create a new WebSocketTransport instance for the new lifecycle"],"exampleFix":"// before\nawait ws.start();\nawait reloadConfig();\nawait ws.start(); // throws: already running\n\n// after\nawait ws.start();\nawait reloadConfig();\nawait ws.stop();\nawait ws.start();","handlingStrategy":"validation","validationCode":"let startPromise: Promise<void> | null = null;\nfunction ensureWsStarted() {\n  return (startPromise ??= wsTransport.start());\n}","typeGuard":null,"tryCatchPattern":"try {\n  await wsTransport.start();\n} catch (e) {\n  if (e instanceof Error && /already running/.test(e.message)) return;\n  throw e;\n}","preventionTips":["Memoize the WebSocket start promise; call it from one owner","Restart via stop() then start(), never start() over a live transport","In reconnect logic, reuse the existing connection instead of re-starting the transport"],"tags":["mcp","transport","websocket","lifecycle","double-start"],"backgroundTag":"server-already-started","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}