{"record":{"id":"ba35fe012e3a9dc7","repo":"ruvnet/ruflo","slug":"server-already-running","errorCode":null,"errorMessage":"Server already running","messagePattern":"Server already running","errorType":"exception","errorClass":"MCPServerError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/shared/src/mcp/server.ts","lineNumber":156,"sourceCode":"    // Initialize connection pool if enabled\n    if (this.config.connectionPool) {\n      this.connectionPool = createConnectionPool(\n        this.config.connectionPool,\n        logger,\n        this.config.transport\n      );\n    }\n\n    // Setup event handlers\n    this.setupEventHandlers();\n  }\n\n  /**\n   * Start the MCP server\n   */\n  async start(): Promise<void> {\n    if (this.running) {\n      throw new MCPServerError('Server already running');\n    }\n\n    const startTime = performance.now();\n    this.startTime = new Date();\n\n    this.logger.info('Starting MCP server', {\n      name: this.config.name,\n      version: this.config.version,\n      transport: this.config.transport,\n    });\n\n    try {\n      // Create and start transport\n      this.transport = createTransport(this.config.transport, this.logger, {\n        type: this.config.transport,\n        host: this.config.host,\n        port: this.config.port,\n        corsEnabled: this.config.corsEnabled,","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/shared/src/mcp/server.ts#L138-L174","documentation":"MCPServer.start() is single-shot: an internal running flag is set while the transport and tool registry come up, and a second start() on the same instance throws MCPServerError('Server already running'). The guard prevents double-binding transports and duplicated event-handler registration. stop() resets the flag, after which start() is legal again.","triggerScenarios":"Awaiting server.start() from two init paths (main + bootstrap helper); a start-retry wrapper that re-invokes start() after a timeout even though the first call actually succeeded; test beforeEach starting a shared server instance that was never stopped.","commonSituations":"Hot reload / dual ESM-CJS module loading so init code runs twice; backoff logic wrapped blindly around startup; conditional branches that both call start(); assuming a previous start failed because a dependent health check was slow.","solutions":["Memoize startup so duplicate calls coalesce: const ready = startPromise ??= server.start()","For a genuine restart, await server.stop() first, then start() again","Make init single-entry: create the server in one module-level singleton reachable from exactly one code path"],"exampleFix":"// before\nawait server.start();\n// later, another init path:\nawait server.start(); // MCPServerError: Server already running\n\n// after\nlet startPromise: Promise<void> | null = null;\nfunction ensureStarted() { return (startPromise ??= server.start()); }\nawait ensureStarted();\nawait ensureStarted(); // coalesced, no throw","handlingStrategy":"validation","validationCode":"let startPromise: Promise<void> | null = null;\nfunction ensureStarted(): Promise<void> {\n  return (startPromise ??= server.start());\n}\nawait ensureStarted(); // safe to call from any init path","typeGuard":null,"tryCatchPattern":"import { MCPServerError } from '@claude-flow/shared/dist/mcp/types';\ntry {\n  await server.start();\n} catch (e) {\n  if (e instanceof MCPServerError && e.message === 'Server already running') {\n    return; // treat as idempotent success\n  }\n  throw e;\n}","preventionTips":["Memoize the start promise instead of calling start() from multiple modules","Pair every restart with stop() first","Create the server in exactly one place (module singleton) and export ensureStarted()"],"tags":["mcp","server","lifecycle","double-start","api-misuse"],"backgroundTag":"server-already-started","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}