{"record":{"id":"0283c9c40e06f978","repo":"ruvnet/ruflo","slug":"transportmanager-already-running-0283c9","errorCode":null,"errorMessage":"TransportManager already running","messagePattern":"TransportManager already running","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/shared/src/mcp/transport/index.ts","lineNumber":186,"sourceCode":"   * Get a transport by name\n   */\n  getTransport(name: string): ITransport | undefined {\n    return this.transports.get(name);\n  }\n\n  /**\n   * Get all transport names\n   */\n  getTransportNames(): string[] {\n    return Array.from(this.transports.keys());\n  }\n\n  /**\n   * Start all transports\n   */\n  async startAll(): Promise<void> {\n    if (this.running) {\n      throw new Error('TransportManager already running');\n    }\n\n    this.logger.info('Starting all transports', { count: this.transports.size });\n\n    const startPromises = Array.from(this.transports.entries()).map(\n      async ([name, transport]) => {\n        try {\n          await transport.start();\n          this.logger.info('Transport started', { name, type: transport.type });\n        } catch (error) {\n          this.logger.error('Failed to start transport', { name, error });\n          throw error;\n        }\n      }\n    );\n\n    await Promise.all(startPromises);\n    this.running = true;","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/shared/src/mcp/transport/index.ts#L168-L204","documentation":"TransportManager.startAll() starts every registered transport and refuses to run twice via its running flag (a public isRunning() accessor exists). A second startAll() - including one issued while the first is still awaiting a slow transport - throws. Note per-transport failures also propagate: if any transport.start() rejects, startAll() logs 'Failed to start transport' and rejects, so retry logic must stopAll() before retrying.","triggerScenarios":"Calling startAll() from two init modules; re-invoking after a first attempt where one transport failed but the manager flag was already set; restart logic that skips stopAll(); racing a health-check that also triggers startup.","commonSituations":"Two subsystems both 'ensuring' the manager is up; retry/backoff around startup; tests reusing a manager across cases without stopping it.","solutions":["Memoize: ready ??= manager.startAll() so concurrent and duplicate calls coalesce","On a failed startAll(), await manager.stopAll() before retrying so state resets cleanly","In restart flows always pair stopAll() then startAll()"],"exampleFix":"// before\nawait manager.startAll();\n// ...\nawait manager.startAll(); // throws: already running\n\n// after\nif (!manager.isRunning()) {\n  await manager.startAll();\n}\n// or memoize:\nconst ready = startPromise ??= manager.startAll();","handlingStrategy":"validation","validationCode":"if (manager.isRunning()) {\n  return; // already up\n}\nawait manager.startAll();","typeGuard":null,"tryCatchPattern":"try {\n  await manager.startAll();\n} catch (e) {\n  if (e instanceof Error && /already running/.test(e.message)) return;\n  // a real transport failure: reset state before any retry\n  await manager.stopAll().catch(() => {});\n  throw e;\n}","preventionTips":["Memoize the startAll promise so concurrent init paths coalesce","Use the public isRunning() accessor before calling startAll()","After a failed startAll(), stopAll() before retrying so manager state resets"],"tags":["mcp","transport","lifecycle","double-start","orchestration"],"backgroundTag":"server-already-started","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}