{"record":{"id":"8619efa11ad8a436","repo":"rohitg00/agentmemory","slug":"circuit-breaker-open","errorCode":"circuit_breaker_open","errorMessage":"circuit_breaker_open","messagePattern":"circuit_breaker_open","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/providers/resilient.ts","lineNumber":14,"sourceCode":"import type { MemoryProvider, CircuitBreakerState } from \"../types.js\";\nimport { CircuitBreaker } from \"./circuit-breaker.js\";\n\nexport class ResilientProvider implements MemoryProvider {\n  private breaker = new CircuitBreaker();\n  name: string;\n\n  constructor(private inner: MemoryProvider) {\n    this.name = `resilient(${inner.name})`;\n  }\n\n  private async call(fn: () => Promise<string>): Promise<string> {\n    if (!this.breaker.isAllowed) {\n      throw new Error(\"circuit_breaker_open\");\n    }\n    try {\n      const result = await fn();\n      this.breaker.recordSuccess();\n      return result;\n    } catch (err) {\n      this.breaker.recordFailure();\n      throw err;\n    }\n  }\n\n  async compress(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(() => this.inner.compress(systemPrompt, userPrompt));\n  }\n\n  async summarize(systemPrompt: string, userPrompt: string): Promise<string> {\n    return this.call(() => this.inner.summarize(systemPrompt, userPrompt));\n  }","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/rohitg00/agentmemory/blob/e04ba88819c365c9acf9d6661ea802143e728bd6/src/providers/resilient.ts#L1-L32","documentation":"ResilientProvider.call checks the CircuitBreaker before delegating to the wrapped MemoryProvider; when the breaker is open (too many recent failures) it throws immediately with the coded error 'circuit_breaker_open' without any network attempt. This is intentional fast-fail backpressure: it protects the upstream LLM API while it is considered unhealthy and lets it recover.","triggerScenarios":"compress()/summarize() called while the breaker for the inner provider is open — i.e. the failure threshold was reached within the breaker's rolling window and the cooldown has not elapsed; every call during the open window throws this instantly.","commonSituations":"Bulk operations looping compress/summarize after an outage or key expiry trips the breaker; a burst of 429/5xx responses opening the breaker, then queued jobs hammering it; long cooldown misread as a 'stuck' provider; tests run without resetting breaker state between cases.","solutions":["Wait for the breaker cooldown to elapse — it will half-open and retry automatically on the next call","Fix the root cause first (key, quota, connectivity) so the half-open probe succeeds","Restart the process to reset breaker state if the window is inappropriate for your workload","Catch this error and queue work for later retry instead of failing the batch","Tune breaker thresholds/cooldown in resilient.ts to match your request volume"],"exampleFix":"// before\nfor (const doc of docs) await provider.compress(doc); // throws circuit_breaker_open mid-batch\n\n// after\nfor (const doc of docs) {\n  try { await provider.compress(doc); }\n  catch (e) { if (e.message === 'circuit_breaker_open') { await sleep(5000); retry(doc); } }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isCircuitOpen(e: unknown): e is Error & { message: 'circuit_breaker_open' } {\n  return e instanceof Error && e.message === 'circuit_breaker_open';\n}","tryCatchPattern":"try {\n  return await resilientProvider.call(prompt);\n} catch (e) {\n  if (isCircuitOpen(e)) {\n    await sleep(jitteredBackoff());\n    return resilientProvider.call(prompt);\n  }\n  throw e;\n}","preventionTips":["Fix upstream root causes (keys, quota, outages) promptly so the breaker can close again","Queue/defer work instead of tight-looping while the breaker is open","Size breaker thresholds and cooldown to your real traffic volume","Reset breaker state between test cases to avoid cross-test flakiness"],"tags":["circuit-breaker","resilience","fast-fail","rate-limiting"],"backgroundTag":"circuit-breaker-open","analyzedSha":"e04ba88819c365c9acf9d6661ea802143e728bd6","analyzedAt":"2026-08-30T01:07:40.754Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}