fix: fail immediately on 400 errors instead of cycling accounts

400 errors (INVALID_ARGUMENT) are client errors that won't be fixed by
switching accounts. Previously the proxy would cycle through all accounts
before returning the error. Now it fails immediately.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Badri Narayanan S
2026-02-01 18:36:07 +05:30
parent ae2cdc0227
commit 2ab0c7943d
2 changed files with 22 additions and 0 deletions

View File

@@ -396,6 +396,13 @@ export async function sendMessage(anthropicRequest, accountManager, fallbackEnab
throw new Error(`CAPACITY_EXHAUSTED: ${errorText}`); throw new Error(`CAPACITY_EXHAUSTED: ${errorText}`);
} }
// 400 errors are client errors - fail immediately, don't retry or switch accounts
// Examples: token limit exceeded, invalid schema, malformed request
if (response.status === 400) {
logger.error(`[CloudCode] Invalid request (400): ${errorText.substring(0, 200)}`);
throw new Error(`invalid_request_error: ${errorText}`);
}
lastError = new Error(`API error ${response.status}: ${errorText}`); lastError = new Error(`API error ${response.status}: ${errorText}`);
// Try next endpoint for 403/404/5xx errors (matches opencode-antigravity-auth behavior) // Try next endpoint for 403/404/5xx errors (matches opencode-antigravity-auth behavior)
if (response.status === 403 || response.status === 404) { if (response.status === 403 || response.status === 404) {
@@ -430,6 +437,10 @@ export async function sendMessage(anthropicRequest, accountManager, fallbackEnab
if (isRateLimitError(endpointError)) { if (isRateLimitError(endpointError)) {
throw endpointError; // Re-throw to trigger account switch throw endpointError; // Re-throw to trigger account switch
} }
// 400 errors are client errors - re-throw immediately, don't retry
if (endpointError.message?.includes('400')) {
throw endpointError;
}
logger.warn(`[CloudCode] Error at ${endpoint}:`, endpointError.message); logger.warn(`[CloudCode] Error at ${endpoint}:`, endpointError.message);
lastError = endpointError; lastError = endpointError;
endpointIndex++; endpointIndex++;

View File

@@ -389,6 +389,13 @@ export async function* sendMessageStream(anthropicRequest, accountManager, fallb
throw new Error(`CAPACITY_EXHAUSTED: ${errorText}`); throw new Error(`CAPACITY_EXHAUSTED: ${errorText}`);
} }
// 400 errors are client errors - fail immediately, don't retry or switch accounts
// Examples: token limit exceeded, invalid schema, malformed request
if (response.status === 400) {
logger.error(`[CloudCode] Invalid request (400): ${errorText.substring(0, 200)}`);
throw new Error(`invalid_request_error: ${errorText}`);
}
lastError = new Error(`API error ${response.status}: ${errorText}`); lastError = new Error(`API error ${response.status}: ${errorText}`);
// Try next endpoint for 403/404/5xx errors (matches opencode-antigravity-auth behavior) // Try next endpoint for 403/404/5xx errors (matches opencode-antigravity-auth behavior)
@@ -488,6 +495,10 @@ export async function* sendMessageStream(anthropicRequest, accountManager, fallb
if (isEmptyResponseError(endpointError)) { if (isEmptyResponseError(endpointError)) {
throw endpointError; throw endpointError;
} }
// 400 errors are client errors - re-throw immediately, don't retry
if (endpointError.message?.includes('400')) {
throw endpointError;
}
logger.warn(`[CloudCode] Stream error at ${endpoint}:`, endpointError.message); logger.warn(`[CloudCode] Stream error at ${endpoint}:`, endpointError.message);
lastError = endpointError; lastError = endpointError;
endpointIndex++; endpointIndex++;