Why a prospect was marked failed on a circuit breaker error

What this page covers

If a LinkedIn prospect on your campaign was marked status='failed' with a last_error field containing the phrase "Circuit breaker is half_open" or "Circuit breaker is open", this guide explains what that error meant pre-V15, what V15 changed (May 7, 2026), and what to expect going forward.

WarmySender is a 4-pillar outreach platform — Cold Emailing, Email Warmup, LinkedIn Outreach, and Multichannel sequences. This page is part of the LinkedIn Outreach pillar and applies to any LinkedIn action type that goes through the unified campaign engine (invites, messages, InMails, profile views, engagements).

What is the circuit breaker, and why does it fire?

WarmySender wraps every Unipile API call in a defensive circuit breaker. The breaker is named MASS-404-BURST internally (covered in detail by LL#244) and exists to protect customer LinkedIn accounts from a specific failure mode: when Unipile's upstream LinkedIn integration starts returning bursts of HTTP 404 responses, retrying every request individually can rapidly degrade into account restriction. The breaker watches the recent Unipile error rate, and when the rate crosses a threshold, it trips.

While the breaker is tripped, every Unipile call from WarmySender's side throws an error of the form Circuit breaker is half_open. Retry after 0s (or Circuit breaker is open. Retry after Ns). This is the breaker doing its job: refusing to send into a known-degraded upstream so the calls don't compound the degradation.

The key distinction: this error is internal load-shedding from our own code, not a signal from LinkedIn that the prospect is unreachable. The prospect is fine; the moment the breaker recovers, the same prospect is fully sendable.

The pre-V15 bug

Before May 7, 2026, the campaign engine's retry handler didn't distinguish internal-circuit-breaker errors from external (LinkedIn-side) failures. Both classes funneled into the same 3-strikes-and-out retry budget. So if the breaker happened to be tripped during 3 different attempts on the same prospect — even attempts spaced an hour apart — the prospect would burn its full retry budget and be marked status='failed' permanently.

This was wrong on three axes:

Production audit on May 7 found Talha's prospect Axel had hit this exact pattern: 3 Circuit breaker is half_open errors in the view_profile retry path, all in a single afternoon during a Unipile-side incident, and the prospect was marked status='failed' as a result.

The V15 fix

V15 introduces a new error classification: circuit_breaker_internal. The engine retry handler now checks every error message against an exact Circuit breaker is prefix matcher BEFORE consulting the retry budget. When matched:

The 60-second floor is account-safety: never re-fire instantly into a still-open breaker (cascading re-trip). The 1-hour ceiling is operator-safety: never strand a prospect for hours if the breaker reports a multi-hour mass-trip — the next scheduler tick will re-check and either succeed or defer again with a fresh retry-after.

What still burns the retry budget

The 3-strikes retry budget is preserved for actual external (LinkedIn-side) failures. Examples that DO consume retry budget:

Examples that DO NOT consume retry budget post-V15 (deferral path):

What to do if you see this in your campaign history

The bug only affected prospects who hit 3 breaker trips before V15 shipped (May 7, 2026). For those prospects:

  1. Open the affected campaign's prospect list. Filter by status=failed.
  2. Inspect each failed prospect's last_error. If it contains "Circuit breaker is half_open" or "Circuit breaker is open" or similar, that's the V15 bug.
  3. Re-enable the prospect. Open the prospect editor, click "Re-enable" to flip status back to scheduled and reset the retry count. The prospect will re-enroll on the next sending window.
  4. Bulk recovery via support. If you have many affected prospects, contact support — we can run a one-shot heal script that re-enables every prospect that failed with this exact error pattern.

Going forward (post-V15), no new prospects can fail for this reason. The breaker-defer path replaces the retry-strike path for every internal-breaker error message.

Account safety

Per CLAUDE.md, account safety is the top invariant of the WarmySender platform. The V15 retry-classifier change is strictly safety-improving:

Frequently asked questions

What's the difference between the MASS-404-BURST circuit breaker and Sales Nav credits-exhausted?

They're two different breakers covering different failure modes:

Both are refusal-to-send patterns, but they fire in different code paths and recover via different signals.

Why does the deferral take up to an hour?

The breaker recovery time is set by the upstream incident's severity. For a fast-half-open trip (retry-after=0s), we still floor at 60s to avoid re-tripping immediately. For a full-open trip with a known multi-minute recovery (retry-after=300s), we honor the breaker's reported time. Anything over 1 hour is clamped to 1 hour because the next scheduler tick will re-check anyway, and we don't want to strand the prospect if the breaker recovers earlier.

Will my campaign appear paused while the breaker is tripped?

No — the campaign continues running. Individual prospects whose attempts hit the tripped breaker are deferred ~60s-1h. The campaign-level status remains running, and the dispatcher will continue to enqueue the next due prospects on the next sending tick.

Can I see when the breaker last tripped?

Operators can grep production logs for "source":"view_profile_circuit_breaker_defer" to see every defer with its retry-after and timestamp. We don't currently expose this directly in the customer dashboard — if your campaigns are seeing systematic deferrals, contact support and we can run an audit query against the campaign-event log for you.

Does this apply to InMail / message / invite steps too, or only view_profile?

It applies to every LinkedIn action type that goes through the unified campaign engine: invites, messages, InMails, view-profile, engage-post, endorse-skill. The classifier matches on the error message prefix (Circuit breaker is ) and the retry-handler block is shared across all action types. The log line says view_profile_circuit_breaker_defer historically because the first audit case was a view_profile step (Axel), but the same defer-not-strike behavior now applies to all action types.

Do I need to do anything to get this fix?

No — the V15 fix shipped May 7, 2026 and applies automatically to every LinkedIn campaign on the platform. Pre-V15 prospects that had already been marked failed are not auto-recovered (we don't unilaterally flip customer-visible state); use the "Re-enable" button on each affected prospect, or contact support for bulk re-enable.