From 0b477c2552a6911c18770d3ab6defbe84e4d72b4 Mon Sep 17 00:00:00 2001 From: Tiago Rodrigues Date: Sat, 10 Jan 2026 12:08:53 +0000 Subject: [PATCH] feat: fallback to alternate model when max retries exceeded with 5xx errors When all accounts fail with HTTP 500/503 errors (e.g., Google API returning 'Unknown Error' for Claude models on large conversations), the proxy now attempts to use a fallback model if --fallback is enabled. This enables graceful degradation when: - All accounts are exhausted due to 5xx errors (not just rate limits) - Claude models fail on very large conversations - The API has temporary issues with specific models The fallback uses the existing MODEL_FALLBACK_MAP configuration: - claude-opus-4-5-thinking -> gemini-3-pro-high - claude-sonnet-4-5-thinking -> gemini-3-flash Relates to #88 --- src/cloudcode/message-handler.js | 10 ++++++++++ src/cloudcode/streaming-handler.js | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/cloudcode/message-handler.js b/src/cloudcode/message-handler.js index fb1ed86..596229d 100644 --- a/src/cloudcode/message-handler.js +++ b/src/cloudcode/message-handler.js @@ -218,5 +218,15 @@ export async function sendMessage(anthropicRequest, accountManager, fallbackEnab } } + // All retries exhausted - try fallback model if enabled + if (fallbackEnabled) { + const fallbackModel = getFallbackModel(model); + if (fallbackModel) { + logger.warn(`[CloudCode] All retries exhausted for ${model}. Attempting fallback to ${fallbackModel}`); + const fallbackRequest = { ...anthropicRequest, model: fallbackModel }; + return await sendMessage(fallbackRequest, accountManager, false); // Disable fallback for recursive call + } + } + throw new Error('Max retries exceeded'); } diff --git a/src/cloudcode/streaming-handler.js b/src/cloudcode/streaming-handler.js index d1d054f..3f0dc55 100644 --- a/src/cloudcode/streaming-handler.js +++ b/src/cloudcode/streaming-handler.js @@ -285,6 +285,17 @@ export async function* sendMessageStream(anthropicRequest, accountManager, fallb } } + // All retries exhausted - try fallback model if enabled + if (fallbackEnabled) { + const fallbackModel = getFallbackModel(model); + if (fallbackModel) { + logger.warn(`[CloudCode] All retries exhausted for ${model}. Attempting fallback to ${fallbackModel} (streaming)`); + const fallbackRequest = { ...anthropicRequest, model: fallbackModel }; + yield* sendMessageStream(fallbackRequest, accountManager, false); // Disable fallback for recursive call + return; + } + } + throw new Error('Max retries exceeded'); }