{"record":{"id":"42897d628b95d1e6","repo":"ruvnet/ruflo","slug":"connection-pool-is-shutting-down","errorCode":null,"errorMessage":"Connection pool is shutting down","messagePattern":"Connection pool is shutting down","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/mcp/src/connection-pool.ts","lineNumber":124,"sourceCode":"\n  private async createConnection(): Promise<ManagedConnection> {\n    const id = `conn-${++this.connectionCounter}-${Date.now()}`;\n    const connection = new ManagedConnection(id, this.transportType);\n\n    this.connections.set(id, connection);\n    this.stats.totalCreated++;\n\n    this.emit('pool:connection:created', { connectionId: id });\n    this.logger.debug('Connection created', { id, total: this.connections.size });\n\n    return connection;\n  }\n\n  async acquire(): Promise<PooledConnection> {\n    const startTime = performance.now();\n\n    if (this.isShuttingDown) {\n      throw new Error('Connection pool is shutting down');\n    }\n\n    for (const connection of this.connections.values()) {\n      if (connection.state === 'idle' && connection.isHealthy()) {\n        connection.acquire();\n        this.stats.totalAcquired++;\n        this.recordAcquireTime(startTime);\n\n        this.emit('pool:connection:acquired', { connectionId: connection.id });\n        this.logger.debug('Connection acquired from pool', { id: connection.id });\n\n        return connection;\n      }\n    }\n\n    if (this.connections.size < this.config.maxConnections) {\n      const connection = await this.createConnection();\n      connection.acquire();","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/mcp/src/connection-pool.ts#L106-L142","documentation":"ConnectionPool.acquire() checks isShuttingDown and refuses new checkouts once shutdown() has begun — the pool is draining existing connections and hands out nothing new. Any acquire that races teardown gets this error.","triggerScenarios":"Calling acquire() after pool.shutdown() started: typically in-flight request handlers, timers, or background jobs that still run during process or service shutdown and attempt a checkout.","commonSituations":"A SIGTERM handler closing the pool while requests are still draining; a timer firing mid-shutdown; cleanup ordering bugs where shutdown runs before the last consumers finish.","solutions":["Fix teardown order: stop accepting/producing work, await in-flight tasks, then call pool.shutdown()","In late-running code, catch this error and skip — acquiring during a drain is a logic bug, not a retryable fault","Gate connection use on your own draining flag set before pool.shutdown()"],"exampleFix":"// before\nprocess.on('SIGTERM', () => pool.shutdown());\nsetInterval(work, 1000); // work() calls pool.acquire() -> throws during drain\n\n// after\nlet draining = false;\nconst timer = setInterval(work, 1000);\nprocess.on('SIGTERM', () => {\n  draining = true;\n  clearInterval(timer);\n  pool.shutdown();\n});\nasync function work() {\n  if (draining) return;\n  const conn = await pool.acquire();\n  // ...\n}","handlingStrategy":"try-catch","validationCode":"// Flip your own gate before initiating shutdown\nlet draining = false;\nasync function shutdown() {\n  draining = true;\n  await inFlight;   // let consumers finish\n  await pool.shutdown();\n}\nasync function withConnection<T>(fn: (c: PooledConnection) => Promise<T>): Promise<T> {\n  if (draining) throw new Error('app draining');\n  return fn(await pool.acquire());\n}","typeGuard":null,"tryCatchPattern":"try {\n  const conn = await pool.acquire();\n} catch (e) {\n  if (e instanceof Error && e.message === 'Connection pool is shutting down') {\n    return; // we're draining — skip this work item entirely, never retry\n  }\n  throw e;\n}","preventionTips":["Shutdown order: stop producers, drain consumers, then close the pool","Never call pool.shutdown() from a signal handler without first stopping timers and background work","Watch the pool's shutdown events to confirm a clean drain before process exit"],"tags":["shutdown","lifecycle","connection-pool","race"],"backgroundTag":"connection-pool-shutting-down","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}