#23502: fix: Anthropic insufficient_quota HTTP 400 does not trigger failover (#23440)
app: web-ui
size: XS
Cluster:
Quota Management Improvements
## Summary
Fixes #23440.
Anthropic returns HTTP 400 (not 402/429) when an account runs out of credits, with an `insufficient_quota` error code in the message. Two bugs prevented failover from triggering:
### Root cause 1 — HTTP 400 masking in `resolveFailoverReasonFromError`
```ts
// before
if (status === 400) return "format";
// after
if (status === 400 && !classifyFailoverReason(getErrorMessage(err))) return "format";
```
The hardcoded early-return meant the message was never inspected. Now HTTP 400 only resolves to `"format"` when the message doesn't match any known failover pattern.
### Root cause 2 — Missing keywords in `ERROR_PATTERNS.billing`
Added `"insufficient_quota"` and `"insufficient quota"` to the billing pattern list so `isBillingErrorMessage()` correctly identifies Anthropic quota errors.
## Tests
- Added `isBillingErrorMessage` test cases for `insufficient_quota` / `insufficient quota` variants
- Added `resolveFailoverReasonFromError` test cases asserting HTTP 400 + quota message → `"billing"`, and plain HTTP 400 still → `"format"`
- All 40 tests pass (`vitest.e2e.config.ts`)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a data loss issue when editing agent configurations through the dashboard. Previously, using `saveConfig()` with `config.set` would replace the entire agents array, silently removing any agents that were added or modified externally (via CLI or file edits) between page load and save. The fix introduces `patchAgentsConfig()` which uses `config.patch` with array merging by ID, preserving external changes while updating only the agents visible in the dashboard.
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge with low risk of issues
- The implementation is straightforward and well-tested (existing e2e tests verify `config.patch` behavior with agent merging). The change is scoped to only agent-related save operations, leaving other config saves unchanged. The server-side `config.patch` method already has validation and proper error handling.
- No files require special attention
<sub>Last reviewed commit: 2b47641</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#23520: fix: trigger failover on Anthropic insufficient_quota (HTTP 400) (#...
by dissaozw · 2026-02-22
92.3%
#6014: Agents: improve quota exhaustion fallback detection
by erain · 2026-02-01
78.8%
#16307: fix: surface billing/auth FailoverErrors as user-friendly messages
by petter-b · 2026-02-14
78.7%
#22359: fix(agents): classify overloaded service errors as timeout
by AIflow-Labs · 2026-02-21
76.9%
#11170: fix: classify subscription quota limit errors as rate_limit for fai...
by Yida-Dev · 2026-02-07
76.5%
#15109: fix: distinguish transient API errors from billing errors
by jwchmodx · 2026-02-13
75.9%
#12314: fix: treat HTTP 5xx server errors as failover-worthy
by hsssgdtc · 2026-02-09
75.7%
#11821: fix(auth): trigger failover on 401 status code from expired OAuth t...
by AnonO6 · 2026-02-08
74.9%
#21491: fix: classify Google 503 UNAVAILABLE as transient failover [AI-assi...
by ZPTDclaw · 2026-02-20
74.2%
#9173: Fix: Improve error messaging for API rate limits and billing errors
by vishaltandale00 · 2026-02-04
74.0%