{"record":{"id":"c817457ae27ff5e8","repo":"ruvnet/ruflo","slug":"http-transport-already-running-c81745","errorCode":null,"errorMessage":"HTTP transport already running","messagePattern":"HTTP transport already running","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/shared/src/mcp/transport/http.ts","lineNumber":86,"sourceCode":"  private httpRequests = 0;\n  private wsMessages = 0;\n\n  constructor(\n    private readonly logger: ILogger,\n    private readonly config: HttpTransportConfig\n  ) {\n    super();\n    this.app = express();\n    this.setupMiddleware();\n    this.setupRoutes();\n  }\n\n  /**\n   * Start the transport\n   */\n  async start(): Promise<void> {\n    if (this.running) {\n      throw new Error('HTTP transport already running');\n    }\n\n    this.logger.info('Starting HTTP transport', {\n      host: this.config.host,\n      port: this.config.port,\n    });\n\n    // Create HTTP server\n    this.server = createServer(this.app);\n\n    // Create WebSocket server\n    this.wss = new WebSocketServer({\n      server: this.server,\n      path: '/ws',\n    });\n\n    this.setupWebSocketHandlers();\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/shared/src/mcp/transport/http.ts#L68-L104","documentation":"HTTPTransport.start() binds an express app via createServer plus a WebSocketServer and is guarded by an internal running flag. A second start() on the same instance throws immediately: the port is already bound by the first start and the middleware/routes/sockets are already installed. stop() closes the server and resets the flag, enabling a stop-then-start restart.","triggerScenarios":"Calling transport.start() twice; restart-on-config-reload code that re-runs setup without stop(); an orchestrator handing the same transport instance to two modules that each start it; retry wrapper around start().","commonSituations":"Config hot-reload rebuilding wiring but reusing the transport object; health-check harness that starts the transport on every probe; module-level transport shared across tests.","solutions":["Memoize the start call: startPromise ??= transport.start()","For restart flows: await transport.stop() before start() again","Alternatively build a fresh HTTPTransport instance for the new lifecycle instead of restarting the old one"],"exampleFix":"// before\nawait transport.start();\nawait reloadConfig();\nawait transport.start(); // throws: already running\n\n// after\nawait transport.start();\nawait reloadConfig();\nawait transport.stop();\nawait transport.start();","handlingStrategy":"validation","validationCode":"let running = false;\nasync function startOnce() {\n  if (running) return;\n  await transport.start();\n  running = true;\n}\nawait startOnce();","typeGuard":null,"tryCatchPattern":"try {\n  await transport.start();\n} catch (e) {\n  if (e instanceof Error && /already running/.test(e.message)) return; // idempotent\n  throw e;\n}","preventionTips":["Memoize the transport start promise","Always stop() before restart; or build a new HTTPTransport for the new lifecycle","Keep transport instances module-scoped with a single owner"],"tags":["mcp","transport","http","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"}