Fixes [API Error: Cannot read properties of undefined (reading 'error')] (#14553)

This commit is contained in:
Silvio Junior
2025-12-04 20:18:37 -05:00
committed by GitHub
parent 290ede93e2
commit 7db5abdecf
2 changed files with 144 additions and 5 deletions

View File

@@ -5,7 +5,13 @@
*/
import { describe, it, expect } from 'vitest';
import { isAuthenticationError, UnauthorizedError } from './errors.js';
import {
isAuthenticationError,
UnauthorizedError,
toFriendlyError,
BadRequestError,
ForbiddenError,
} from './errors.js';
describe('isAuthenticationError', () => {
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);
});
});
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);
});
});

View File

@@ -92,7 +92,7 @@ export function toFriendlyError(error: unknown): unknown {
if (error && typeof error === 'object' && 'response' in error) {
const gaxiosError = error as 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) {
case 400:
return new BadRequestError(data.error.message);
@@ -110,12 +110,16 @@ export function toFriendlyError(error: unknown): unknown {
return error;
}
function parseResponseData(error: GaxiosError): ResponseData {
function parseResponseData(error: GaxiosError): ResponseData | undefined {
// Inexplicably, Gaxios sometimes doesn't JSONify the response data.
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;
}
/**