[FEATURE] Automatic Model Fallback on API Errors (529/429)

Resolved 💬 3 comments Opened Feb 3, 2026 by ninad-kale Closed Feb 7, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Feature Request: Automatic Model Fallback on API Errors (529/429)

Problem: When using Opus 4.5 and encountering 529 (overloaded) errors, the session stalls or fails. Users must manually switch models with /model sonnet.

Requested Feature:

  1. Automatic fallback: When Claude Code encounters repeated 529/429 errors with the primary model, automatically fall back to a specified secondary model (e.g.,

Sonnet)

  1. UI notification: Display a clear indicator when running in "degraded mode" so users understand they're getting a smaller model's capabilities
  2. Configuration: Allow users to configure fallback behavior in settings:

{
"model": "opus",
"fallbackModel": "sonnet",
"fallbackAfterErrors": 3,
"showDegradedModeIndicator": true
}

Why it matters: This would make Claude Code more resilient during high-traffic periods and set proper user expectations about model capabilities.

Proposed Solution

Proposed Solution

  1. Configuration Schema

Add new fields to settings.json:

{
"model": "opus",
"modelFallback": {
"enabled": true,
"fallbackModel": "sonnet",
"triggerAfterErrors": 3,
"errorCodes": [529, 429],
"cooldownMinutes": 5
}
}

  1. Implementation Approach

A. Error Detection Layer

  • Intercept HTTP responses in the API client layer
  • Track consecutive error counts per error code
  • Reset counter on successful requests

B. Model Switching Logic
if (consecutiveErrors >= triggerAfterErrors && errorCode in errorCodes):
currentModel = fallbackModel
degradedMode = true
startCooldownTimer()

C. Recovery Logic

  • After cooldownMinutes, attempt one request with primary model
  • If successful, exit degraded mode
  • If failed, restart cooldown timer
  1. UI Indicator

Display in the status line when in degraded mode:
⚠️ Degraded mode: Using sonnet (opus unavailable)

Or a persistent banner:
[DEGRADED] Running on sonnet due to API errors. Will retry opus in 4m.

  1. CLI Override

Allow users to force primary model despite errors:
claude --no-fallback

  1. Events/Hooks (Optional)

Add new hook events:

  • ModelFallbackTriggered - fires when switching to fallback
  • ModelFallbackRecovered - fires when returning to primary

This would let users run custom scripts (notifications, logging) when fallback occurs.

Alternative Solutions

Proposed Solution

  1. Configuration Schema

Add new fields to settings.json:

{
"model": "opus",
"modelFallback": {
"enabled": true,
"fallbackModel": "sonnet",
"triggerAfterErrors": 3,
"errorCodes": [529, 429],
"cooldownMinutes": 5
}
}

  1. Implementation Approach

A. Error Detection Layer

  • Intercept HTTP responses in the API client layer
  • Track consecutive error counts per error code
  • Reset counter on successful requests

B. Model Switching Logic
if (consecutiveErrors >= triggerAfterErrors && errorCode in errorCodes):
currentModel = fallbackModel
degradedMode = true
startCooldownTimer()

C. Recovery Logic

  • After cooldownMinutes, attempt one request with primary model
  • If successful, exit degraded mode
  • If failed, restart cooldown timer
  1. UI Indicator

Display in the status line when in degraded mode:
⚠️ Degraded mode: Using sonnet (opus unavailable)

Or a persistent banner:
[DEGRADED] Running on sonnet due to API errors. Will retry opus in 4m.

  1. CLI Override

Allow users to force primary model despite errors:
claude --no-fallback

  1. Events/Hooks (Optional)

Add new hook events:

  • ModelFallbackTriggered - fires when switching to fallback
  • ModelFallbackRecovered - fires when returning to primary

This would let users run custom scripts (notifications, logging) when fallback occurs.

Priority

Critical - Blocking my work

Feature Category

Interactive mode (TUI)

Use Case Example

_No response_

Additional Context

_No response_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗