← Back to PRs

#17231: fix(failover): recognize model_cooldown as rate-limit for fallback

by thebtf open 2026-02-15 15:11 View on GitHub →
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