Gmail error handling fixes (#16719)
- Replaced direct instance checks for GaxiosError with a utility function isGmailApiError for better error handling consistency across services. - Debug logs
This commit is contained in:
+7
-4
@@ -1,11 +1,10 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GaxiosError } from 'gaxios';
|
||||
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { isGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-api-error.util';
|
||||
import { isGmailNetworkError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-network-error.util';
|
||||
import { parseGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-api-error.util';
|
||||
import { parseGmailNetworkError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-network-error.util';
|
||||
@@ -17,12 +16,16 @@ export class GmailEmailAliasErrorHandlerService {
|
||||
constructor() {}
|
||||
|
||||
public handleError(error: unknown): void {
|
||||
this.logger.error(`Google: Error getting email aliases: ${error}`);
|
||||
const constructorName = (error as unknown)?.constructor?.name ?? 'Unknown';
|
||||
|
||||
this.logger.error(
|
||||
`Google: Error getting email aliases: ${error}, constructor: ${constructorName}`,
|
||||
);
|
||||
if (isGmailNetworkError(error)) {
|
||||
throw parseGmailNetworkError(error);
|
||||
}
|
||||
|
||||
if (error instanceof GaxiosError) {
|
||||
if (isGmailApiError(error)) {
|
||||
throw parseGmailApiError(error);
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -1,11 +1,10 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GaxiosError } from 'gaxios';
|
||||
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { isGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-api-error.util';
|
||||
import { isGmailNetworkError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-network-error.util';
|
||||
import { parseGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-api-error.util';
|
||||
import { parseGmailNetworkError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-network-error.util';
|
||||
@@ -17,14 +16,16 @@ export class GmailFoldersErrorHandlerService {
|
||||
constructor() {}
|
||||
|
||||
public handleError(error: unknown): void {
|
||||
const constructorName = (error as unknown)?.constructor?.name ?? 'Unknown';
|
||||
|
||||
this.logger.error(
|
||||
`Gmail: Error fetching folders: ${JSON.stringify(error)}`,
|
||||
`Gmail: Error fetching folders: ${JSON.stringify(error)}, constructor: ${constructorName}`,
|
||||
);
|
||||
if (isGmailNetworkError(error)) {
|
||||
throw parseGmailNetworkError(error);
|
||||
}
|
||||
|
||||
if (error instanceof GaxiosError) {
|
||||
if (isGmailApiError(error)) {
|
||||
throw parseGmailApiError(error);
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -1,11 +1,10 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GaxiosError } from 'gaxios';
|
||||
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { isGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-api-error.util';
|
||||
import { isGmailNetworkError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-network-error.util';
|
||||
import { parseGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-api-error.util';
|
||||
import { parseGmailNetworkError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-network-error.util';
|
||||
@@ -17,14 +16,16 @@ export class GmailMessageListFetchErrorHandler {
|
||||
constructor() {}
|
||||
|
||||
public handleError(error: unknown): void {
|
||||
const constructorName = (error as unknown)?.constructor?.name ?? 'Unknown';
|
||||
|
||||
this.logger.error(
|
||||
`Gmail: Error fetching message list: ${JSON.stringify(error)}`,
|
||||
`Gmail: Error fetching message list: ${JSON.stringify(error)}, constructor: ${constructorName}`,
|
||||
);
|
||||
if (isGmailNetworkError(error)) {
|
||||
throw parseGmailNetworkError(error);
|
||||
}
|
||||
|
||||
if (error instanceof GaxiosError) {
|
||||
if (isGmailApiError(error)) {
|
||||
throw parseGmailApiError(error);
|
||||
}
|
||||
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import { GaxiosError } from 'gaxios';
|
||||
|
||||
import { isGmailApiError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-gmail-api-error.util';
|
||||
|
||||
describe('isGmailApiError', () => {
|
||||
it('should detect Gmail API error shape even when instanceof GaxiosError fails', () => {
|
||||
const originalError = new GaxiosError(
|
||||
'Rate limit exceeded',
|
||||
{},
|
||||
{
|
||||
status: 429,
|
||||
statusText: 'Too Many Requests',
|
||||
headers: {},
|
||||
config: {},
|
||||
request: { responseURL: '' },
|
||||
data: {
|
||||
error: {
|
||||
errors: [
|
||||
{ reason: 'rateLimitExceeded', message: 'Rate limit exceeded' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const serialized = JSON.parse(JSON.stringify(originalError));
|
||||
|
||||
expect(serialized instanceof GaxiosError).toBe(false);
|
||||
expect(isGmailApiError(serialized)).toBe(true);
|
||||
});
|
||||
|
||||
it('should detect error when data.error is a string instead of object', () => {
|
||||
const error = {
|
||||
response: {
|
||||
status: 429,
|
||||
data: {
|
||||
error: 'userRateLimitExceeded',
|
||||
error_description: 'User Rate Limit Exceeded',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(isGmailApiError(error)).toBe(true);
|
||||
});
|
||||
|
||||
it('should reject network errors that have no response', () => {
|
||||
const networkError = new Error('connect ECONNREFUSED');
|
||||
|
||||
expect(isGmailApiError(networkError)).toBe(false);
|
||||
});
|
||||
});
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { type GaxiosError } from 'gaxios';
|
||||
import { z } from 'zod';
|
||||
|
||||
const gmailApiErrorSchema = z.object({
|
||||
response: z.object({
|
||||
status: z.number().optional(),
|
||||
data: z
|
||||
.object({
|
||||
error: z
|
||||
.union([
|
||||
z.object({
|
||||
errors: z
|
||||
.array(
|
||||
z.object({
|
||||
reason: z.string().optional(),
|
||||
message: z.string().optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
}),
|
||||
z.string(),
|
||||
])
|
||||
.optional(),
|
||||
error_description: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const isGmailApiError = (error: unknown): error is GaxiosError => {
|
||||
return gmailApiErrorSchema.safeParse(error).success;
|
||||
};
|
||||
Reference in New Issue
Block a user