ruvnet/ruflo · critical

Circuit breaker open for provider: ${provider}

Error message

Circuit breaker open for provider: ${provider}

What it means

Thrown by MultiModelRouter before executing a completion (v3/@claude-flow/integration/src/multi-model-router.ts:579) when the selected provider's circuit breaker is open. recordFailure() opens the circuit once failureCount reaches circuitBreaker.failureThreshold (default 5, multi-model-router.ts:463/1020) and a setTimeout resets it after circuitBreaker.resetTimeout, emitting a 'circuit:open' event. The throw means: this provider recently failed repeatedly, so the router refuses to send more traffic to it right now.

Source

Thrown at v3/@claude-flow/integration/src/multi-model-router.ts:579

    let provider = request.provider;
    let model = request.model;

    if (!provider || !model) {
      const routing = await this.route({
        task: 'completion',
        messages: request.messages,
        requiredCapabilities: {
          supportsTools: request.tools !== undefined,
          supportsJson: request.responseFormat === 'json',
        },
      });
      provider = routing.provider;
      model = routing.model;
    }

    // Check circuit breaker
    if (this.isCircuitOpen(provider)) {
      throw new Error(`Circuit breaker open for provider: ${provider}`);
    }

    const startTime = performance.now();

    try {
      // Execute completion via provider API
      const response = await this.executeCompletion(request, provider, model);

      // Update health
      this.recordSuccess(provider, performance.now() - startTime);

      // Update cost tracker
      this.trackCost(provider, model, response.cost, response.usage);

      // Cache response
      if (this.config.cacheTTL && !request.stream) {
        this.cache.set(cacheKey, {
          response,

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Fix the underlying provider failure first — check the key, quota, and provider status page; the breaker is a symptom, not the cause.
  2. Retry after circuitBreaker.resetTimeout (the circuit auto-half-opens via the scheduled reset) with backoff instead of immediate retries.
  3. Enable fallback routing so requests go to another healthy provider while one circuit is open (listen for the 'circuit:open' event and reroute).
  4. Tune circuitBreaker.failureThreshold / resetTimeout (and consider treating 429 as backoff rather than failure) so transient blips do not trip the breaker.

Example fix

// before
const res = await router.complete(request); // throws while circuit open

// after
try {
  const res = await router.complete(request);
} catch (e) {
  if ((e as Error).message.startsWith('Circuit breaker open')) {
    await sleep(resetTimeoutMs); // wait for the scheduled reset
    return router.complete(request);
  }
  throw e;
}
Defensive patterns

Strategy: fallback

Validate before calling

router.on('circuit:open', ({ provider }) => {
  disabledProviders.add(provider); // consult before routing
});
// before calling complete(): route around providers in disabledProviders

Type guard

function isCircuitBreakerError(e: unknown): e is Error {
  return e instanceof Error && e.message.startsWith('Circuit breaker open for provider:');
}

Try / catch

try {
  return await router.complete(request);
} catch (e) {
  if (isCircuitBreakerError(e)) {
    await sleep(resetTimeoutMs); // circuit auto-resets via scheduled timeout
    return router.complete(request);
  }
  throw e;
}

Prevention

When it happens

Trigger: A provider (OpenAI, Anthropic, etc.) returning 5xx/429/network errors five times in a row; API key revoked or quota exhausted producing consistent failures; downstream outage while your code keeps calling complete() — each call fails fast with this error until resetTimeout elapses.

Common situations: Expired/invalid API key causing every attempt to fail until the breaker trips; rate limiting (429s) counted as failures; regional outage; too-low failureThreshold with flaky networks; tests hammering a mocked-down provider.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/783fd8721961ed2c. Report an issue: GitHub.