{"record":{"id":"081d95090df6fde8","repo":"ruvnet/ruflo","slug":"circuit-breaker-this-name-is-open","errorCode":null,"errorMessage":"Circuit breaker ${this.name} is open","messagePattern":"Circuit breaker (.+?) is open","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/providers/src/base-provider.ts","lineNumber":53,"sourceCode":" * Simple circuit breaker implementation\n */\nclass CircuitBreaker {\n  private failures = 0;\n  private lastFailure = 0;\n  private state: 'closed' | 'open' | 'half-open' = 'closed';\n\n  constructor(\n    private readonly name: string,\n    private readonly threshold: number = 5,\n    private readonly resetTimeout: number = 60000\n  ) {}\n\n  async execute<T>(fn: () => Promise<T>): Promise<T> {\n    if (this.state === 'open') {\n      if (Date.now() - this.lastFailure > this.resetTimeout) {\n        this.state = 'half-open';\n      } else {\n        throw new Error(`Circuit breaker ${this.name} is open`);\n      }\n    }\n\n    try {\n      const result = await fn();\n      this.onSuccess();\n      return result;\n    } catch (error) {\n      this.onFailure();\n      throw error;\n    }\n  }\n\n  private onSuccess(): void {\n    this.failures = 0;\n    this.state = 'closed';\n  }\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/providers/src/base-provider.ts#L35-L71","documentation":"Every provider built on BaseProvider wraps its doComplete/doStreamComplete calls in a CircuitBreaker. After `threshold` consecutive failures (default 5) the breaker flips to 'open' and this error is thrown immediately, without contacting the upstream API. Once `resetTimeout` ms (default 60000) elapse since the last failure, the next call transitions the breaker to 'half-open' and lets a trial request through.","triggerScenarios":"Calling provider.complete() or provider.streamComplete() while that provider instance's breaker is 'open' and fewer than 60 s (resetTimeout) have passed since the last failure - e.g. the upstream API returned 429/5xx/timeout five times in a row and you retry a sixth time within the window.","commonSituations":"Sustained upstream outage or aggressive rate limiting that trips the breaker; a tight retry loop hammering the provider; config.timeout set too small so every call times out; one shared provider instance absorbing failures from many concurrent requests.","solutions":["Wait out the reset window (default 60 s) before the next call - the breaker then moves to half-open and allows one trial request; do not retry immediately","Fix the underlying failures that opened it: inspect logs for the AuthenticationError / RateLimitError / LLMProviderError thrown just before the breaker opened","Tune threshold and resetTimeout in the provider options if 5 failures / 60 s trips too easily for your traffic shape","Recreate or re-initialize the provider to get a fresh breaker once you know upstream is healthy again"],"exampleFix":"// before\nconst provider = manager.getProvider('openai');\nawait provider.complete(req); // throws: Circuit breaker openai is open\n\n// after - back off for the reset window, then retry once (half-open trial)\ntry {\n  await provider.complete(req);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Circuit breaker')) {\n    await new Promise(r => setTimeout(r, 60_000));\n    await provider.complete(req);\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"export function isCircuitBreakerOpen(e: unknown): boolean {\n  return e instanceof Error && /^Circuit breaker .+ is open$/.test(e.message);\n}","tryCatchPattern":"try {\n  return await provider.complete(req);\n} catch (e) {\n  if (isCircuitBreakerOpen(e)) {\n    await new Promise(r => setTimeout(r, 60_000 + Math.random() * 5_000)); // resetTimeout + jitter\n    return provider.complete(req); // single half-open trial retry\n  }\n  throw e;\n}","preventionTips":["Wrap complete()/streamComplete() in retry-with-backoff instead of tight loops","Track provider healthCheck() and stop dispatching while a breaker is open","Size config.timeout to the model's real latency so slow responses do not count as failures","Tune threshold/resetTimeout to your request volume before shipping"],"tags":["circuit-breaker","resilience","transient","retry","llm-provider"],"backgroundTag":"circuit-breaker-open","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}