summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/utils/errorParsing.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/utils/errorParsing.test.ts')
-rw-r--r--packages/cli/src/ui/utils/errorParsing.test.ts309
1 files changed, 304 insertions, 5 deletions
diff --git a/packages/cli/src/ui/utils/errorParsing.test.ts b/packages/cli/src/ui/utils/errorParsing.test.ts
index 4bbaabf1..3d228efb 100644
--- a/packages/cli/src/ui/utils/errorParsing.test.ts
+++ b/packages/cli/src/ui/utils/errorParsing.test.ts
@@ -6,10 +6,16 @@
import { describe, it, expect } from 'vitest';
import { parseAndFormatApiError } from './errorParsing.js';
-import { AuthType, StructuredError } from '@google/gemini-cli-core';
+import {
+ AuthType,
+ UserTierId,
+ DEFAULT_GEMINI_FLASH_MODEL,
+ isProQuotaExceededError,
+} from '@google/gemini-cli-core';
describe('parseAndFormatApiError', () => {
- const enterpriseMessage = 'upgrade to a plan with higher limits';
+ const _enterpriseMessage =
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits';
const vertexMessage = 'request a quota increase through Vertex';
const geminiMessage = 'request a quota increase through AI Studio';
@@ -24,9 +30,17 @@ describe('parseAndFormatApiError', () => {
it('should format a 429 API error with the default message', () => {
const errorMessage =
'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
- const result = parseAndFormatApiError(errorMessage);
+ const result = parseAndFormatApiError(
+ errorMessage,
+ undefined,
+ undefined,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
expect(result).toContain('[API Error: Rate limit exceeded');
- expect(result).toContain('Your request has been rate limited');
+ expect(result).toContain(
+ 'Slow response times detected. Switching to the gemini-2.5-flash model',
+ );
});
it('should format a 429 API error with the personal message', () => {
@@ -35,9 +49,14 @@ describe('parseAndFormatApiError', () => {
const result = parseAndFormatApiError(
errorMessage,
AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
);
expect(result).toContain('[API Error: Rate limit exceeded');
- expect(result).toContain(enterpriseMessage);
+ expect(result).toContain(
+ 'Slow response times detected. Switching to the gemini-2.5-flash model',
+ );
});
it('should format a 429 API error with the vertex message', () => {
@@ -116,4 +135,284 @@ describe('parseAndFormatApiError', () => {
const expected = '[API Error: An unknown error occurred.]';
expect(parseAndFormatApiError(error)).toBe(expected);
});
+
+ it('should format a 429 API error with Pro quota exceeded message for Google auth (Free tier)', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain(
+ "[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'",
+ );
+ expect(result).toContain(
+ 'You have reached your daily gemini-2.5-pro quota limit',
+ );
+ expect(result).toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ });
+
+ it('should format a regular 429 API error with standard message for Google auth', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain('[API Error: Rate limit exceeded');
+ expect(result).toContain(
+ 'Slow response times detected. Switching to the gemini-2.5-flash model',
+ );
+ expect(result).not.toContain(
+ 'You have reached your daily gemini-2.5-pro quota limit',
+ );
+ });
+
+ it('should format a 429 API error with generic quota exceeded message for Google auth', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'GenerationRequests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain(
+ "[API Error: Quota exceeded for quota metric 'GenerationRequests'",
+ );
+ expect(result).toContain('You have reached your daily quota limit');
+ expect(result).not.toContain(
+ 'You have reached your daily Gemini 2.5 Pro quota limit',
+ );
+ });
+
+ it('should prioritize Pro quota message over generic quota message for Google auth', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain(
+ "[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'",
+ );
+ expect(result).toContain(
+ 'You have reached your daily gemini-2.5-pro quota limit',
+ );
+ expect(result).not.toContain('You have reached your daily quota limit');
+ });
+
+ it('should format a 429 API error with Pro quota exceeded message for Google auth (Standard tier)', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ UserTierId.STANDARD,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain(
+ "[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'",
+ );
+ expect(result).toContain(
+ 'You have reached your daily gemini-2.5-pro quota limit',
+ );
+ expect(result).toContain(
+ 'We appreciate you for choosing Gemini Code Assist and the Gemini CLI',
+ );
+ expect(result).not.toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ });
+
+ it('should format a 429 API error with Pro quota exceeded message for Google auth (Legacy tier)', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ UserTierId.LEGACY,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain(
+ "[API Error: Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'",
+ );
+ expect(result).toContain(
+ 'You have reached your daily gemini-2.5-pro quota limit',
+ );
+ expect(result).toContain(
+ 'We appreciate you for choosing Gemini Code Assist and the Gemini CLI',
+ );
+ expect(result).not.toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ });
+
+ it('should handle different Gemini version strings in Pro quota exceeded errors', () => {
+ const errorMessage15 =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 1.5 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const errorMessagePreview =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini 2.5-preview Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const errorMessageBeta =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini beta-3.0 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const errorMessageExperimental =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'Gemini experimental-v2 Pro Requests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+
+ const result15 = parseAndFormatApiError(
+ errorMessage15,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-1.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ const resultPreview = parseAndFormatApiError(
+ errorMessagePreview,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-2.5-preview-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ const resultBeta = parseAndFormatApiError(
+ errorMessageBeta,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-beta-3.0-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ const resultExperimental = parseAndFormatApiError(
+ errorMessageExperimental,
+ AuthType.LOGIN_WITH_GOOGLE,
+ undefined,
+ 'gemini-experimental-v2-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+
+ expect(result15).toContain(
+ 'You have reached your daily gemini-1.5-pro quota limit',
+ );
+ expect(resultPreview).toContain(
+ 'You have reached your daily gemini-2.5-preview-pro quota limit',
+ );
+ expect(resultBeta).toContain(
+ 'You have reached your daily gemini-beta-3.0-pro quota limit',
+ );
+ expect(resultExperimental).toContain(
+ 'You have reached your daily gemini-experimental-v2-pro quota limit',
+ );
+ expect(result15).toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ expect(resultPreview).toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ expect(resultBeta).toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ expect(resultExperimental).toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ });
+
+ it('should not match non-Pro models with similar version strings', () => {
+ // Test that Flash models with similar version strings don't match
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'Gemini 2.5 Flash Requests' and limit",
+ ),
+ ).toBe(false);
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'Gemini 2.5-preview Flash Requests' and limit",
+ ),
+ ).toBe(false);
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'Gemini beta-3.0 Flash Requests' and limit",
+ ),
+ ).toBe(false);
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'Gemini experimental-v2 Flash Requests' and limit",
+ ),
+ ).toBe(false);
+
+ // Test other model types
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'Gemini 2.5 Ultra Requests' and limit",
+ ),
+ ).toBe(false);
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'Gemini 2.5 Standard Requests' and limit",
+ ),
+ ).toBe(false);
+
+ // Test generic quota messages
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'GenerationRequests' and limit",
+ ),
+ ).toBe(false);
+ expect(
+ isProQuotaExceededError(
+ "Quota exceeded for quota metric 'EmbeddingRequests' and limit",
+ ),
+ ).toBe(false);
+ });
+
+ it('should format a generic quota exceeded message for Google auth (Standard tier)', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Quota exceeded for quota metric \'GenerationRequests\' and limit \'RequestsPerDay\' of service \'generativelanguage.googleapis.com\' for consumer \'project_number:123456789\'.","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ UserTierId.STANDARD,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain(
+ "[API Error: Quota exceeded for quota metric 'GenerationRequests'",
+ );
+ expect(result).toContain('You have reached your daily quota limit');
+ expect(result).toContain(
+ 'We appreciate you for choosing Gemini Code Assist and the Gemini CLI',
+ );
+ expect(result).not.toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ });
+
+ it('should format a regular 429 API error with standard message for Google auth (Standard tier)', () => {
+ const errorMessage =
+ 'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}';
+ const result = parseAndFormatApiError(
+ errorMessage,
+ AuthType.LOGIN_WITH_GOOGLE,
+ UserTierId.STANDARD,
+ 'gemini-2.5-pro',
+ DEFAULT_GEMINI_FLASH_MODEL,
+ );
+ expect(result).toContain('[API Error: Rate limit exceeded');
+ expect(result).toContain(
+ 'We appreciate you for choosing Gemini Code Assist and the Gemini CLI',
+ );
+ expect(result).not.toContain(
+ 'upgrade to a Gemini Code Assist Standard or Enterprise plan',
+ );
+ });
});