mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-24 03:54:43 -07:00
feat: better error messages (#20577)
Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com> # Conflicts: # packages/cli/src/test-utils/render.tsx # packages/cli/src/ui/AppContainer.tsx # packages/cli/src/ui/contexts/UIActionsContext.tsx # packages/core/src/utils/errors.test.ts # packages/core/src/utils/errors.ts
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
toFriendlyError,
|
||||
BadRequestError,
|
||||
ForbiddenError,
|
||||
AccountSuspendedError,
|
||||
getErrorMessage,
|
||||
} from './errors.js';
|
||||
|
||||
@@ -119,9 +120,86 @@ describe('toFriendlyError', () => {
|
||||
};
|
||||
const result = toFriendlyError(error);
|
||||
expect(result).toBeInstanceOf(ForbiddenError);
|
||||
expect(result).not.toBeInstanceOf(AccountSuspendedError);
|
||||
expect((result as ForbiddenError).message).toBe('Forbidden');
|
||||
});
|
||||
|
||||
it('should return AccountSuspendedError for 403 with TOS_VIOLATION reason in details', () => {
|
||||
const error = {
|
||||
response: {
|
||||
data: {
|
||||
error: {
|
||||
code: 403,
|
||||
message:
|
||||
'This service has been disabled in this account for violation of Terms of Service.',
|
||||
details: [
|
||||
{
|
||||
'@type': 'type.googleapis.com/google.rpc.ErrorInfo',
|
||||
reason: 'TOS_VIOLATION',
|
||||
domain: 'example.googleapis.com',
|
||||
metadata: {
|
||||
uiMessage: 'true',
|
||||
appeal_url_link_text: 'Appeal Here',
|
||||
appeal_url: 'https://example.com/appeal',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = toFriendlyError(error);
|
||||
expect(result).toBeInstanceOf(AccountSuspendedError);
|
||||
expect(result).toBeInstanceOf(ForbiddenError);
|
||||
const suspended = result as AccountSuspendedError;
|
||||
expect(suspended.message).toBe(
|
||||
'This service has been disabled in this account for violation of Terms of Service.',
|
||||
);
|
||||
expect(suspended.appealUrl).toBe('https://example.com/appeal');
|
||||
expect(suspended.appealLinkText).toBe('Appeal Here');
|
||||
});
|
||||
|
||||
it('should return ForbiddenError for 403 with violation message but no TOS_VIOLATION detail', () => {
|
||||
const error = {
|
||||
response: {
|
||||
data: {
|
||||
error: {
|
||||
code: 403,
|
||||
message:
|
||||
'This service has been disabled in this account for violation of Terms of Service.',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = toFriendlyError(error);
|
||||
expect(result).toBeInstanceOf(ForbiddenError);
|
||||
expect(result).not.toBeInstanceOf(AccountSuspendedError);
|
||||
});
|
||||
|
||||
it('should return ForbiddenError for 403 with non-TOS_VIOLATION detail', () => {
|
||||
const error = {
|
||||
response: {
|
||||
data: {
|
||||
error: {
|
||||
code: 403,
|
||||
message: 'Forbidden',
|
||||
details: [
|
||||
{
|
||||
'@type': 'type.googleapis.com/google.rpc.ErrorInfo',
|
||||
reason: 'ACCESS_DENIED',
|
||||
domain: 'googleapis.com',
|
||||
metadata: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = toFriendlyError(error);
|
||||
expect(result).toBeInstanceOf(ForbiddenError);
|
||||
expect(result).not.toBeInstanceOf(AccountSuspendedError);
|
||||
});
|
||||
|
||||
it('should parse stringified JSON data', () => {
|
||||
const error = {
|
||||
response: {
|
||||
@@ -201,3 +279,50 @@ describe('toFriendlyError', () => {
|
||||
expect(toFriendlyError(error)).toBe(error);
|
||||
});
|
||||
});
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
describe('getErrorType', () => {
|
||||
it('should return error name for standard errors', () => {
|
||||
expect(getErrorType(new Error('test'))).toBe('Error');
|
||||
expect(getErrorType(new TypeError('test'))).toBe('TypeError');
|
||||
expect(getErrorType(new SyntaxError('test'))).toBe('SyntaxError');
|
||||
});
|
||||
|
||||
it('should return constructor name for custom errors', () => {
|
||||
expect(getErrorType(new FatalAuthenticationError('test'))).toBe(
|
||||
'FatalAuthenticationError',
|
||||
);
|
||||
expect(getErrorType(new FatalInputError('test'))).toBe('FatalInputError');
|
||||
expect(getErrorType(new FatalSandboxError('test'))).toBe(
|
||||
'FatalSandboxError',
|
||||
);
|
||||
expect(getErrorType(new FatalConfigError('test'))).toBe('FatalConfigError');
|
||||
expect(getErrorType(new FatalTurnLimitedError('test'))).toBe(
|
||||
'FatalTurnLimitedError',
|
||||
);
|
||||
expect(getErrorType(new FatalToolExecutionError('test'))).toBe(
|
||||
'FatalToolExecutionError',
|
||||
);
|
||||
expect(getErrorType(new FatalCancellationError('test'))).toBe(
|
||||
'FatalCancellationError',
|
||||
);
|
||||
expect(getErrorType(new ForbiddenError('test'))).toBe('ForbiddenError');
|
||||
expect(getErrorType(new AccountSuspendedError('test'))).toBe(
|
||||
'AccountSuspendedError',
|
||||
);
|
||||
expect(getErrorType(new UnauthorizedError('test'))).toBe(
|
||||
'UnauthorizedError',
|
||||
);
|
||||
expect(getErrorType(new BadRequestError('test'))).toBe('BadRequestError');
|
||||
});
|
||||
|
||||
it('should return "unknown" for non-Error objects', () => {
|
||||
expect(getErrorType('string error')).toBe('unknown');
|
||||
expect(getErrorType(123)).toBe('unknown');
|
||||
expect(getErrorType({})).toBe('unknown');
|
||||
expect(getErrorType(null)).toBe('unknown');
|
||||
expect(getErrorType(undefined)).toBe('unknown');
|
||||
});
|
||||
});
|
||||
>>>>>>> ea48bd941 (feat: better error messages (#20577))
|
||||
|
||||
Reference in New Issue
Block a user