mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-30 06:54:15 -07:00
Fixes [API Error: Cannot read properties of undefined (reading 'error')] (#14553)
This commit is contained in:
@@ -5,7 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { isAuthenticationError, UnauthorizedError } from './errors.js';
|
import {
|
||||||
|
isAuthenticationError,
|
||||||
|
UnauthorizedError,
|
||||||
|
toFriendlyError,
|
||||||
|
BadRequestError,
|
||||||
|
ForbiddenError,
|
||||||
|
} from './errors.js';
|
||||||
|
|
||||||
describe('isAuthenticationError', () => {
|
describe('isAuthenticationError', () => {
|
||||||
it('should detect error with code: 401 property (MCP SDK style)', () => {
|
it('should detect error with code: 401 property (MCP SDK style)', () => {
|
||||||
@@ -40,3 +46,132 @@ describe('isAuthenticationError', () => {
|
|||||||
expect(isAuthenticationError(new Error('Status code: 401'))).toBe(true);
|
expect(isAuthenticationError(new Error('Status code: 401'))).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('toFriendlyError', () => {
|
||||||
|
it('should return BadRequestError for 400', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
code: 400,
|
||||||
|
message: 'Bad Request',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const result = toFriendlyError(error);
|
||||||
|
expect(result).toBeInstanceOf(BadRequestError);
|
||||||
|
expect((result as BadRequestError).message).toBe('Bad Request');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return UnauthorizedError for 401', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
code: 401,
|
||||||
|
message: 'Unauthorized',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const result = toFriendlyError(error);
|
||||||
|
expect(result).toBeInstanceOf(UnauthorizedError);
|
||||||
|
expect((result as UnauthorizedError).message).toBe('Unauthorized');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return ForbiddenError for 403', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
code: 403,
|
||||||
|
message: 'Forbidden',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const result = toFriendlyError(error);
|
||||||
|
expect(result).toBeInstanceOf(ForbiddenError);
|
||||||
|
expect((result as ForbiddenError).message).toBe('Forbidden');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse stringified JSON data', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: JSON.stringify({
|
||||||
|
error: {
|
||||||
|
code: 400,
|
||||||
|
message: 'Parsed Message',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const result = toFriendlyError(error);
|
||||||
|
expect(result).toBeInstanceOf(BadRequestError);
|
||||||
|
expect((result as BadRequestError).message).toBe('Parsed Message');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original error if response data is undefined', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(toFriendlyError(error)).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original error if error object is missing in data', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
somethingElse: 'value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(toFriendlyError(error)).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original error if error code or message is missing', () => {
|
||||||
|
const errorNoCode = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
message: 'No Code',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(toFriendlyError(errorNoCode)).toBe(errorNoCode);
|
||||||
|
|
||||||
|
const errorNoMessage = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
code: 400,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(toFriendlyError(errorNoMessage)).toBe(errorNoMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original error for unknown codes', () => {
|
||||||
|
const error = {
|
||||||
|
response: {
|
||||||
|
data: {
|
||||||
|
error: {
|
||||||
|
code: 500,
|
||||||
|
message: 'Internal Server Error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(toFriendlyError(error)).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original error if not a Gaxios error object', () => {
|
||||||
|
const error = new Error('Regular Error');
|
||||||
|
expect(toFriendlyError(error)).toBe(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export function toFriendlyError(error: unknown): unknown {
|
|||||||
if (error && typeof error === 'object' && 'response' in error) {
|
if (error && typeof error === 'object' && 'response' in error) {
|
||||||
const gaxiosError = error as GaxiosError;
|
const gaxiosError = error as GaxiosError;
|
||||||
const data = parseResponseData(gaxiosError);
|
const data = parseResponseData(gaxiosError);
|
||||||
if (data.error && data.error.message && data.error.code) {
|
if (data && data.error && data.error.message && data.error.code) {
|
||||||
switch (data.error.code) {
|
switch (data.error.code) {
|
||||||
case 400:
|
case 400:
|
||||||
return new BadRequestError(data.error.message);
|
return new BadRequestError(data.error.message);
|
||||||
@@ -110,12 +110,16 @@ export function toFriendlyError(error: unknown): unknown {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseResponseData(error: GaxiosError): ResponseData {
|
function parseResponseData(error: GaxiosError): ResponseData | undefined {
|
||||||
// Inexplicably, Gaxios sometimes doesn't JSONify the response data.
|
// Inexplicably, Gaxios sometimes doesn't JSONify the response data.
|
||||||
if (typeof error.response?.data === 'string') {
|
if (typeof error.response?.data === 'string') {
|
||||||
return JSON.parse(error.response?.data) as ResponseData;
|
try {
|
||||||
|
return JSON.parse(error.response?.data) as ResponseData;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return error.response?.data as ResponseData;
|
return error.response?.data as ResponseData | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user