2025-06-07 22:04:57 -07:00
/ * *
* @license
* Copyright 2025 Google LLC
* SPDX - License - Identifier : Apache - 2.0
* /
import { describe , it , expect } from 'vitest' ;
import { parseAndFormatApiError } from './errorParsing.js' ;
2025-08-13 17:57:11 +00:00
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js' ;
import { AuthType } from '../core/contentGenerator.js' ;
2025-08-26 00:04:53 +02:00
import type { StructuredError } from '../core/turn.js' ;
2025-06-07 22:04:57 -07:00
describe ( 'parseAndFormatApiError' , ( ) = > {
2025-06-23 23:43:00 -04:00
const vertexMessage = 'request a quota increase through Vertex' ;
const geminiMessage = 'request a quota increase through AI Studio' ;
2025-06-23 17:30:13 -04:00
2025-06-07 22:04:57 -07:00
it ( 'should format a valid API error JSON' , ( ) = > {
const errorMessage =
'got status: 400 Bad Request. {"error":{"code":400,"message":"API key not valid. Please pass a valid API key.","status":"INVALID_ARGUMENT"}}' ;
const expected =
2025-06-23 17:30:13 -04:00
'[API Error: API key not valid. Please pass a valid API key. (Status: INVALID_ARGUMENT)]' ;
expect ( parseAndFormatApiError ( errorMessage ) ) . toBe ( expected ) ;
} ) ;
2025-06-23 23:43:00 -04:00
it ( 'should format a 429 API error with the default message' , ( ) = > {
2025-06-23 17:30:13 -04:00
const errorMessage =
'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}' ;
2025-07-09 10:18:15 -04:00
const result = parseAndFormatApiError (
errorMessage ,
undefined ,
undefined ,
'gemini-2.5-pro' ,
DEFAULT_GEMINI_FLASH_MODEL ,
) ;
2025-06-23 23:43:00 -04:00
expect ( result ) . toContain ( '[API Error: Rate limit exceeded' ) ;
2025-07-09 10:18:15 -04:00
expect ( result ) . toContain (
2025-07-09 13:55:56 -04:00
'Possible quota limitations in place or slow response times detected. Switching to the gemini-2.5-flash model' ,
2025-07-09 10:18:15 -04:00
) ;
2025-06-23 23:43:00 -04:00
} ) ;
it ( 'should format a 429 API error with the vertex message' , ( ) = > {
const errorMessage =
'got status: 429 Too Many Requests. {"error":{"code":429,"message":"Rate limit exceeded","status":"RESOURCE_EXHAUSTED"}}' ;
const result = parseAndFormatApiError ( errorMessage , AuthType . USE_VERTEX_AI ) ;
expect ( result ) . toContain ( '[API Error: Rate limit exceeded' ) ;
expect ( result ) . toContain ( vertexMessage ) ;
2025-06-07 22:04:57 -07:00
} ) ;
it ( 'should return the original message if it is not a JSON error' , ( ) = > {
const errorMessage = 'This is a plain old error message' ;
2025-06-23 17:30:13 -04:00
expect ( parseAndFormatApiError ( errorMessage ) ) . toBe (
` [API Error: ${ errorMessage } ] ` ,
) ;
2025-06-07 22:04:57 -07:00
} ) ;
it ( 'should return the original message for malformed JSON' , ( ) = > {
const errorMessage = '[Stream Error: {"error": "malformed}' ;
2025-06-23 17:30:13 -04:00
expect ( parseAndFormatApiError ( errorMessage ) ) . toBe (
` [API Error: ${ errorMessage } ] ` ,
) ;
2025-06-07 22:04:57 -07:00
} ) ;
it ( 'should handle JSON that does not match the ApiError structure' , ( ) = > {
const errorMessage = '[Stream Error: {"not_an_error": "some other json"}]' ;
2025-06-23 17:30:13 -04:00
expect ( parseAndFormatApiError ( errorMessage ) ) . toBe (
` [API Error: ${ errorMessage } ] ` ,
) ;
2025-06-07 22:04:57 -07:00
} ) ;
it ( 'should format a nested API error' , ( ) = > {
const nestedErrorMessage = JSON . stringify ( {
error : {
code : 429 ,
message :
"Gemini 2.5 Pro Preview doesn't have a free quota tier. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits." ,
status : 'RESOURCE_EXHAUSTED' ,
} ,
} ) ;
const errorMessage = JSON . stringify ( {
error : {
code : 429 ,
message : nestedErrorMessage ,
status : 'Too Many Requests' ,
} ,
} ) ;
2025-06-23 23:43:00 -04:00
const result = parseAndFormatApiError ( errorMessage , AuthType . USE_GEMINI ) ;
expect ( result ) . toContain ( 'Gemini 2.5 Pro Preview' ) ;
expect ( result ) . toContain ( geminiMessage ) ;
2025-06-23 17:30:13 -04:00
} ) ;
it ( 'should format a StructuredError' , ( ) = > {
const error : StructuredError = {
message : 'A structured error occurred' ,
status : 500 ,
} ;
const expected = '[API Error: A structured error occurred]' ;
expect ( parseAndFormatApiError ( error ) ) . toBe ( expected ) ;
} ) ;
2025-06-23 23:43:00 -04:00
it ( 'should format a 429 StructuredError with the vertex message' , ( ) = > {
2025-06-23 17:30:13 -04:00
const error : StructuredError = {
message : 'Rate limit exceeded' ,
status : 429 ,
} ;
2025-06-23 23:43:00 -04:00
const result = parseAndFormatApiError ( error , AuthType . USE_VERTEX_AI ) ;
expect ( result ) . toContain ( '[API Error: Rate limit exceeded]' ) ;
expect ( result ) . toContain ( vertexMessage ) ;
2025-06-23 17:30:13 -04:00
} ) ;
it ( 'should handle an unknown error type' , ( ) = > {
const error = 12345 ;
const expected = '[API Error: An unknown error occurred.]' ;
expect ( parseAndFormatApiError ( error ) ) . toBe ( expected ) ;
2025-06-07 22:04:57 -07:00
} ) ;
} ) ;