2025-06-07 22:04:57 -07:00
/ * *
* @license
* Copyright 2025 Google LLC
* SPDX - License - Identifier : Apache - 2.0
* /
2025-06-25 05:41:11 -07:00
import { AuthType , StructuredError } from '@google/gemini-cli-core' ;
2025-06-23 17:30:13 -04:00
2025-06-23 23:43:00 -04:00
const RATE_LIMIT_ERROR_MESSAGE_GOOGLE =
2025-06-23 17:30:13 -04:00
'\nPlease wait and try again later. To increase your limits, upgrade to a plan with higher limits, or use /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey' ;
2025-06-23 23:43:00 -04:00
const RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI =
'\nPlease wait and try again later. To increase your limits, request a quota increase through AI Studio, or switch to another /auth method' ;
const RATE_LIMIT_ERROR_MESSAGE_VERTEX =
'\nPlease wait and try again later. To increase your limits, request a quota increase through Vertex, or switch to another /auth method' ;
const RATE_LIMIT_ERROR_MESSAGE_DEFAULT =
'Your request has been rate limited. Please wait and try again later.' ;
2025-06-23 17:30:13 -04:00
2025-06-07 22:04:57 -07:00
export interface ApiError {
error : {
code : number ;
message : string ;
status : string ;
details : unknown [ ] ;
} ;
}
function isApiError ( error : unknown ) : error is ApiError {
return (
typeof error === 'object' &&
error !== null &&
'error' in error &&
typeof ( error as ApiError ) . error === 'object' &&
'message' in ( error as ApiError ) . error
) ;
}
2025-06-23 17:30:13 -04:00
function isStructuredError ( error : unknown ) : error is StructuredError {
return (
typeof error === 'object' &&
error !== null &&
'message' in error &&
typeof ( error as StructuredError ) . message === 'string'
) ;
}
2025-06-23 23:43:00 -04:00
function getRateLimitMessage ( authType? : AuthType ) : string {
switch ( authType ) {
2025-06-30 17:11:54 -07:00
case AuthType . LOGIN_WITH_GOOGLE :
2025-06-23 23:43:00 -04:00
return RATE_LIMIT_ERROR_MESSAGE_GOOGLE ;
case AuthType . USE_GEMINI :
return RATE_LIMIT_ERROR_MESSAGE_USE_GEMINI ;
case AuthType . USE_VERTEX_AI :
return RATE_LIMIT_ERROR_MESSAGE_VERTEX ;
default :
return RATE_LIMIT_ERROR_MESSAGE_DEFAULT ;
}
}
export function parseAndFormatApiError (
error : unknown ,
authType? : AuthType ,
) : string {
2025-06-23 17:30:13 -04:00
if ( isStructuredError ( error ) ) {
let text = ` [API Error: ${ error . message } ] ` ;
if ( error . status === 429 ) {
2025-06-23 23:43:00 -04:00
text += getRateLimitMessage ( authType ) ;
2025-06-23 17:30:13 -04:00
}
return text ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
// The error message might be a string containing a JSON object.
if ( typeof error === 'string' ) {
const jsonStart = error . indexOf ( '{' ) ;
if ( jsonStart === - 1 ) {
return ` [API Error: ${ error } ] ` ; // Not a JSON error, return as is.
}
const jsonString = error . substring ( jsonStart ) ;
try {
const parsedError = JSON . parse ( jsonString ) as unknown ;
if ( isApiError ( parsedError ) ) {
let finalMessage = parsedError . error . message ;
try {
// See if the message is a stringified JSON with another error
const nestedError = JSON . parse ( finalMessage ) as unknown ;
if ( isApiError ( nestedError ) ) {
finalMessage = nestedError . error . message ;
}
} catch ( _e ) {
// It's not a nested JSON error, so we just use the message as is.
}
let text = ` [API Error: ${ finalMessage } (Status: ${ parsedError . error . status } )] ` ;
if ( parsedError . error . code === 429 ) {
2025-06-23 23:43:00 -04:00
text += getRateLimitMessage ( authType ) ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
return text ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
} catch ( _e ) {
// Not a valid JSON, fall through and return the original message.
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
return ` [API Error: ${ error } ] ` ;
2025-06-07 22:04:57 -07:00
}
2025-06-23 17:30:13 -04:00
return '[API Error: An unknown error occurred.]' ;
2025-06-07 22:04:57 -07:00
}