{"record":{"id":"773fcb82e1faffdf","repo":"Billionmail/BillionMail","slug":"circuit-breaker-s-w","errorCode":null,"errorMessage":"circuit breaker [%s]: %w","messagePattern":"circuit breaker \\[(.+?)\\]: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/video_gen/apiclient.go","lineNumber":49,"sourceCode":"\t\t\t\treturn counts.ConsecutiveFailures >= 5\n\t\t\t},\n\t\t}),\n\t}\n}\n\n// Do executes an HTTP request with rate limiting and circuit breaking.\n// Blocks until rate limiter allows, then executes through circuit breaker.\nfunc (c *RateLimitedClient) Do(req *http.Request) (*http.Response, error) {\n\tctx := req.Context()\n\tif err := c.limiter.Wait(ctx); err != nil {\n\t\treturn nil, fmt.Errorf(\"rate limiter: %w\", err)\n\t}\n\n\tresp, err := c.cb.Execute(func() (*http.Response, error) {\n\t\treturn c.client.Do(req)\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"circuit breaker [%s]: %w\", c.cb.Name(), err)\n\t}\n\treturn resp, nil\n}\n","sourceCodeStart":31,"sourceCodeEnd":53,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/video_gen/apiclient.go#L31-L53","documentation":"Do executes the HTTP request through a circuit breaker (c.cb.Execute). When the breaker itself returns an error — the call failed and was counted, or the breaker is open and short-circuits the call — it is wrapped as 'circuit breaker [<name>]: %w'. Inspect the wrapped error to distinguish 'breaker open' from an underlying transport failure.","triggerScenarios":"c.cb.Execute returns an error: the underlying HTTP request failed (network error, connection refused, TLS failure), or the circuit breaker is in the open state and rejects the call outright without attempting the request.","commonSituations":"Repeated upstream API failures tripped the breaker and now all requests fail fast with 'circuit breaker open'; upstream API outage; DNS/network problems in the deployment; too-sensitive breaker thresholds tripping on a transient blip.","solutions":["Read the wrapped error: 'circuit breaker does not allow requests' means the breaker is open — wait for the cool-down or reset it","Fix the underlying transport failure shown by the wrapped error (connectivity, DNS, TLS)","Check recent upstream API health; the breaker likely tripped on a real outage","Tune breaker thresholds (failure count, open duration) if it trips too easily for your traffic","Retry after the breaker's cool-down window rather than hammering the open breaker"],"exampleFix":"// before\nresp, err := client.Do(req)\nif err != nil { return nil, err } // treated as immediate fatal\n// after\nresp, err := client.Do(req)\nvar breakerErr *sonyflake.CircuitOpenError // or check strings.Contains(err.Error(), \"open\")\nif err != nil {\n    if isCircuitOpen(err) { return retryAfterCooldown(req) }\n    return nil, err\n}","handlingStrategy":"try-catch","validationCode":"// check breaker state before sending if the API exposes it\nif cb.State() == circuit.Open {\n    return errors.New(\"skipping call: circuit breaker open, will retry after cooldown\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Do(req)\nif err != nil {\n    if strings.Contains(err.Error(), \"circuit breaker\") && strings.Contains(err.Error(), \"open\") {\n        time.Sleep(cbCooldown) // wait for the breaker to half-open, then retry\n        return retry(req)\n    }\n    // otherwise it's the underlying transport error — log and surface it\n    return fmt.Errorf(\"upstream call failed: %w\", err)\n}","preventionTips":["Distinguish breaker-open errors from transport errors via errors.Unwrap","Set breaker thresholds proportional to your traffic (avoid tripping on one blip)","Add upstream health checks so the breaker can half-open and recover promptly","Use exponential backoff with jitter when retrying against an open breaker"],"tags":["circuit-breaker","http","resilience","network"],"backgroundTag":"circuit-breaker-open","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}