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:
neo773
2025-12-19 22:53:14 +05:30
committed by GitHub
parent d30580fc4e
commit 0849dda153
5 changed files with 100 additions and 12 deletions
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
});
});
@@ -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;
};