#17231: fix(failover): recognize model_cooldown as rate-limit for fallback
agents
size: XS
## Summary
- CLIProxyAPI Plus returns `model_cooldown: All credentials for model X are cooling down` when all API keys for a model hit 429 rate limits
- This error was not matched by any `ERROR_PATTERNS` entry, causing `classifyFailoverReason()` to return `null`
- As a result, `runWithModelFallback()` threw immediately instead of advancing to the next candidate in the fallback chain
- Added `"model_cooldown"` and `"cooling down"` to the `rateLimit` pattern list so the error triggers model fallback
## Details
When using OpenClaw with CLIProxyAPI Plus as a provider, if all API credentials for a given model enter cooldown (due to upstream 429 rate limits), CLIProxyAPI returns an error with type `model_cooldown` and message text containing "cooling down".
Without this fix, `coerceToFailoverError()` cannot wrap this as a `FailoverError`, so the error is thrown directly to the user instead of triggering fallback to the next model in the chain.
## Validation
- [x] `pnpm build` — passes
- [x] `pnpm check` — passes
- [x] `pnpm test` — passes (no existing tests cover this specific pattern; the change adds string literals to an existing array)
- [x] Tested manually with CLIProxyAPI Plus: confirmed fallback triggers on `model_cooldown` errors
## Contribution checklist
- [x] **Focused scope**: 2-line addition of string patterns to an existing array — single concern
- [x] **What + why**: described above
- [x] **AI-assisted**: Yes, Claude Code was used to identify the root cause and draft the fix. The change was reviewed and tested manually. Testing level: lightly tested (manual verification with live CLIProxyAPI Plus instance)
## Test plan
- [ ] Configure a model with fallback chain (e.g., `gemini-3-pro-preview` → `minimax-m2.5-free`)
- [ ] Trigger `model_cooldown` error from CLIProxyAPI (rate-limit all credentials for primary model)
- [ ] Verify agent falls back to next model instead of showing error to user
- [ ] Verify `classifyFailoverReason("model_cooldown: All credentials...")` returns `"rate_limit"`
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds `"model_cooldown"` and `"cooling down"` to the `rateLimit` error patterns in `ERROR_PATTERNS`, so that CLIProxyAPI Plus cooldown errors (returned when all API keys for a model hit upstream 429 rate limits) are correctly classified as rate-limit errors by `classifyFailoverReason()`. Without this fix, these errors were unrecognized, causing `coerceToFailoverError()` to return `null` and `runWithModelFallback()` to throw immediately instead of advancing to the next model in the fallback chain.
- The change is a 2-line addition of string literals to an existing array — minimal scope, no structural changes.
- The new patterns are specific enough to avoid false positives with other error categories (`auth`, `billing`, `timeout`, etc.).
- No tests were added; the PR author notes this is consistent with the existing pattern — other string entries in `ERROR_PATTERNS` also lack individual test coverage.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it adds two string literals to an existing pattern list with no risk of behavioral regression.
- The change is a 2-line addition of string patterns to an existing array. The matching logic (`matchesErrorPatterns` using `.includes()`) is well-established and used by all other entries. The new strings are specific to CLIProxyAPI Plus error responses and won't false-positive against other error categories. The failover pipeline (`classifyFailoverReason` → `coerceToFailoverError` → `runWithModelFallback`) is thoroughly understood and the fix correctly slots into the existing architecture.
- No files require special attention.
<sub>Last reviewed commit: 0cac9be</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#19267: fix: derive failover reason from timedOut flag to prevent unknown c...
by austenstone · 2026-02-17
79.7%
#22064: fix(failover): bypass models allowlist for configured fallback models
by winston-bepresent · 2026-02-20
79.3%
#21033: fix(failover): classify connection errors as timeout for model fail...
by zerone0x · 2026-02-19
78.9%
#21049: fix(failover): treat HTTP 5xx as rate-limit for model fallback
by maximalmargin · 2026-02-19
77.6%
#17531: fix(auth): sync Codex CLI credentials into auth profile store and c...
by sauerdaniel · 2026-02-15
77.4%
#23816: fix(agents): model fallback skipped during session overrides and pr...
by ramezgaberiel · 2026-02-22
77.2%
#21152: fix(agents): throw FailoverError for unknown model so fallback chai...
by Mellowambience · 2026-02-19
77.2%
#14914: fix: resolve actual failure reason for cooldown-skipped providers
by mcaxtr · 2026-02-12
77.0%
#21516: fix: classify connection errors as timeout for model failover (#20931)
by echoVic · 2026-02-20
76.9%
#11821: fix(auth): trigger failover on 401 status code from expired OAuth t...
by AnonO6 · 2026-02-08
76.3%