From 723f269df64c8de56ae1df736f14b556f0d26735 Mon Sep 17 00:00:00 2001 From: Sehoon Shon Date: Fri, 20 Feb 2026 14:51:53 -0500 Subject: [PATCH] fix(core): treat 503 Service Unavailable as retryable quota error (#19642) --- .../scripts/fetch-pr-info.js | 3 ++- .../core/src/utils/googleQuotaErrors.test.ts | 18 +++++++++++++++++- packages/core/src/utils/googleQuotaErrors.ts | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/.gemini/skills/pr-address-comments/scripts/fetch-pr-info.js b/.gemini/skills/pr-address-comments/scripts/fetch-pr-info.js index 772f8d18a4..de99def0ce 100755 --- a/.gemini/skills/pr-address-comments/scripts/fetch-pr-info.js +++ b/.gemini/skills/pr-address-comments/scripts/fetch-pr-info.js @@ -20,7 +20,8 @@ async function run(cmd) { stdio: ['pipe', 'pipe', 'ignore'], }); return stdout.trim(); - } catch (_e) { // eslint-disable-line @typescript-eslint/no-unused-vars + } catch (_e) { + // eslint-disable-line @typescript-eslint/no-unused-vars return null; } } diff --git a/packages/core/src/utils/googleQuotaErrors.test.ts b/packages/core/src/utils/googleQuotaErrors.test.ts index c75eb8de4f..06bde6444b 100644 --- a/packages/core/src/utils/googleQuotaErrors.test.ts +++ b/packages/core/src/utils/googleQuotaErrors.test.ts @@ -65,7 +65,23 @@ describe('classifyGoogleError', () => { expect((result as RetryableQuotaError).message).toBe(rawError.message); }); - it('should return original error if code is not 429', () => { + it('should return RetryableQuotaError for 503 Service Unavailable', () => { + const apiError: GoogleApiError = { + code: 503, + message: 'Service Unavailable', + details: [], + }; + vi.spyOn(errorParser, 'parseGoogleApiError').mockReturnValue(apiError); + const originalError = new Error('Service Unavailable'); + const result = classifyGoogleError(originalError); + expect(result).toBeInstanceOf(RetryableQuotaError); + if (result instanceof RetryableQuotaError) { + expect(result.cause).toBe(apiError); + expect(result.message).toBe('Service Unavailable'); + } + }); + + it('should return original error if code is not 429 or 503', () => { const apiError: GoogleApiError = { code: 500, message: 'Server error', diff --git a/packages/core/src/utils/googleQuotaErrors.ts b/packages/core/src/utils/googleQuotaErrors.ts index 0ecc14d93f..40c1c34361 100644 --- a/packages/core/src/utils/googleQuotaErrors.ts +++ b/packages/core/src/utils/googleQuotaErrors.ts @@ -202,6 +202,21 @@ export function classifyGoogleError(error: unknown): unknown { } } + // Check for 503 Service Unavailable errors + if (status === 503) { + const errorMessage = + googleApiError?.message || + (error instanceof Error ? error.message : String(error)); + return new RetryableQuotaError( + errorMessage, + googleApiError ?? { + code: 503, + message: errorMessage, + details: [], + }, + ); + } + if ( !googleApiError || googleApiError.code !== 429 ||