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
- Fix the underlying provider failure first — check the key, quota, and provider status page; the breaker is a symptom, not the cause.
- Retry after circuitBreaker.resetTimeout (the circuit auto-half-opens via the scheduled reset) with backoff instead of immediate retries.
- Enable fallback routing so requests go to another healthy provider while one circuit is open (listen for the 'circuit:open' event and reroute).
- 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
- Fix root-cause provider failures (keys, quota, network) — the breaker only reflects them.
- Listen to 'circuit:open' events and reroute to healthy providers instead of retrying the same one.
- Tune failureThreshold/resetTimeout and classify 429s as backoff, not hard failures.
- Back off while the circuit is open; hammering complete() just fails fast every time.
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
- Circuit breaker is open. Service temporarily unavailable.
- Circuit breaker ${this.name} is open
- MCP server "${server.name}" is in cooldown (HTTP ${cd.status
- swarm state is busy; retry the outcome update
- Unknown template preset: ${template}. Use: ${Object.keys(pre
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/783fd8721961ed2c.
Report an issue: GitHub.