mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-28 16:09:34 +00:00
classifySelectionFailureError upgrades a selection failure to 429 rate_limit_error whenever the scheduler's compact reason string matches model_rate_limited=(\d+) with a positive count. It does so unconditionally, including when the fallback it was handed is the authoritative 404 model_not_found classification. Selection failure reasons are additive, so both can appear at once, e.g. "pool=9, filtered: model_not_supported=8 model_rate_limited=1": eight accounts cannot serve the model at all and the ninth happens to sit in a per-model cooldown. classifyNoAccountError only produces ModelNotFound through DiagnoseModelAvailabilityForPlatform, a dedicated database query over persistent eligibility (active + schedulable + model_mapping), so it has already established that no account in the group can serve the model. One transient cooldown does not make "All available accounts are currently rate-limited" true. The mislabel is not cosmetic: - Retrying can never succeed, yet 429 explicitly invites a retry. - Clients that treat 429 as a rate limit retry hard and swallow the body; Codex surfaces only "exceeded retry limit, last status: 429", discarding the one message that names the real problem. Operators then look for capacity and rate limits instead of a model whitelist. - Ops attribution becomes self-contradictory: classifyNoAccountErrorFromGin has already marked the request business-limited for local model configuration, while call sites gate markOpsRoutingCapacityLimitedIfNoAvailable on ModelNotFound, which the override clears, so the same request is also counted as routing capacity limited. Return the fallback untouched when it is ModelNotFound. The 429 upgrade is preserved for every other fallback, which is the case it was written for: accounts that can serve the model exist but are all cooling down, where the fallback is 503 and retrying is meaningful. Claude-Session: https://claude.ai/code/session_01LwvyJVV2sdqiu41Z9JDNUq