From 481d149c9b2786dd2360f3ee0ab220660d461178 Mon Sep 17 00:00:00 2001 From: Sankeerth Date: Tue, 3 Dec 2024 09:12:00 +0530 Subject: [PATCH] chore: update default case handling in facebook destinations (#3908) * chore: update default case handling in facebook destinations * fix: update default handling for some error codes - used error_user_msg field as error message - when no error is seen, handled error by stringifying - update test-cases --------- Co-authored-by: Sai Sankeerth --- src/v0/util/facebookUtils/networkHandler.js | 38 +++++----- .../facebook_pixel/dataDelivery/business.ts | 4 +- .../facebook_pixel/dataDelivery/data.ts | 70 +++++++++++++++++-- .../facebook_pixel/dataDelivery/oauth.ts | 4 +- .../facebook_pixel/dataDelivery/other.ts | 10 +-- .../destinations/facebook_pixel/network.ts | 26 +++++++ .../destinations/fb/dataDelivery/data.ts | 3 +- .../destinations/fb/dataDelivery/other.ts | 4 +- test/integrations/destinations/fb/network.ts | 1 + .../fb_custom_audience/dataDelivery/data.ts | 2 + .../fb_custom_audience/network.ts | 2 + 11 files changed, 132 insertions(+), 32 deletions(-) diff --git a/src/v0/util/facebookUtils/networkHandler.js b/src/v0/util/facebookUtils/networkHandler.js index fbb7899efe..46ac59a07a 100644 --- a/src/v0/util/facebookUtils/networkHandler.js +++ b/src/v0/util/facebookUtils/networkHandler.js @@ -85,7 +85,10 @@ const errorDetailsMap = { "Object with ID 'PIXEL_ID' / 'DATASET_ID' / 'AUDIENCE_ID' does not exist, cannot be loaded due to missing permissions, or does not support this operation", ) .build(), - default: new ErrorDetailsExtractorBuilder().setStatus(400).setMessageField('message').build(), + default: new ErrorDetailsExtractorBuilder() + .setStatus(400) + .setMessageField('error_user_msg') + .build(), }, 1: { // An unknown error occurred. @@ -107,9 +110,7 @@ const errorDetailsMap = { .setStat({ [TAG_NAMES.ERROR_TYPE]: ERROR_TYPES.AUTH, }) - .setMessage( - 'The session has been invalidated because the user changed their password or Facebook has changed the session for security reasons', - ) + .setMessageField('error_user_msg') .build(), 463: new ErrorDetailsExtractorBuilder() @@ -117,56 +118,56 @@ const errorDetailsMap = { .setStat({ [TAG_NAMES.ERROR_TYPE]: ERROR_TYPES.AUTH, }) - .setMessageField('message') + .setMessageField('error_user_msg') .build(), default: new ErrorDetailsExtractorBuilder() .setStatus(400) .setStat({ [TAG_NAMES.ERROR_TYPE]: ERROR_TYPES.AUTH, }) - .setMessage('Invalid OAuth 2.0 access token') + .setMessageField('error_user_msg') .build(), }, 3: { default: new ErrorDetailsExtractorBuilder() .setStatus(400) - .setMessage('Capability or permissions issue.') + .setMessageField('error_user_msg') .build(), }, 2: { default: new ErrorDetailsExtractorBuilder() .setStatus(500) - .setMessage('Temporary issue due to downtime.') + .setMessageField('error_user_msg') .build(), }, 341: { default: new ErrorDetailsExtractorBuilder() .setStatus(500) - .setMessage('Application limit reached: Temporary issue due to downtime or throttling') + .setMessageField('error_user_msg') .build(), }, 368: { default: new ErrorDetailsExtractorBuilder() .setStatus(500) - .setMessage('Temporarily blocked for policies violations.') + .setMessageField('error_user_msg') .build(), }, 5000: { default: new ErrorDetailsExtractorBuilder() .setStatus(500) - .setMessage('Unknown Error Code') + .setMessageField('error_user_msg') .build(), }, 4: { default: new ErrorDetailsExtractorBuilder() .setStatus(429) - .setMessage('API Too Many Calls') + .setMessageField('error_user_msg') .build(), }, 17: { default: new ErrorDetailsExtractorBuilder() .setStatus(429) - .setMessage('API User Too Many Calls') + .setMessageField('error_user_msg') .build(), }, // facebook custom audience related error codes @@ -176,9 +177,7 @@ const errorDetailsMap = { 294: { default: new ErrorDetailsExtractorBuilder() .setStatus(400) - .setMessage( - 'Missing permission. Please make sure you have ads_management permission and the application is included in the allowlist', - ) + .setMessageField('error_user_msg') .build(), }, 1487301: { @@ -214,7 +213,10 @@ const errorDetailsMap = { .build(), }, 200: { - default: new ErrorDetailsExtractorBuilder().setStatus(403).setMessageField('message').build(), + default: new ErrorDetailsExtractorBuilder() + .setStatus(403) + .setMessageField('error_user_msg') + .build(), }, 21009: { default: new ErrorDetailsExtractorBuilder().setStatus(500).setMessageField('message').build(), @@ -236,9 +238,11 @@ const getStatus = (error) => { const isErrorDetailEmpty = isEmpty(errorDetail); if (isErrorDetailEmpty) { // Unhandled error response + const errorMessage = get(error?.error || error, 'error_user_msg'); return { status: errorStatus, stats: { [TAG_NAMES.META]: METADATA.UNHANDLED_STATUS_CODE }, + errorMessage: errorMessage || JSON.stringify(error), }; } errorStatus = errorDetail.status; diff --git a/test/integrations/destinations/facebook_pixel/dataDelivery/business.ts b/test/integrations/destinations/facebook_pixel/dataDelivery/business.ts index 1b425ac5fa..2b4af61ac3 100644 --- a/test/integrations/destinations/facebook_pixel/dataDelivery/business.ts +++ b/test/integrations/destinations/facebook_pixel/dataDelivery/business.ts @@ -42,7 +42,7 @@ export const testScenariosForV1API: ProxyV1TestData[] = [ body: { output: { status: 400, - message: 'Invalid OAuth 2.0 access token', + message: 'The access token could not be decrypted', statTags: { ...statTags, errorCategory: 'dataValidation', @@ -51,7 +51,7 @@ export const testScenariosForV1API: ProxyV1TestData[] = [ }, response: [ { - error: 'Invalid OAuth 2.0 access token', + error: 'The access token could not be decrypted', statusCode: 400, metadata: generateMetadata(1), }, diff --git a/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts b/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts index 3366e62c5a..0e004c1183 100644 --- a/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts +++ b/test/integrations/destinations/facebook_pixel/dataDelivery/data.ts @@ -45,12 +45,13 @@ export const v0TestData = [ body: { output: { status: 400, - message: 'Invalid OAuth 2.0 access token', + message: 'The access token could not be decrypted', destinationResponse: { error: { code: 190, fbtrace_id: 'fbpixel_trace_id', message: 'The access token could not be decrypted', + error_user_msg: 'The access token could not be decrypted', type: 'OAuthException', }, status: 500, @@ -202,7 +203,7 @@ export const v0TestData = [ body: { output: { status: 429, - message: 'API User Too Many Calls', + message: 'User request limit reached', destinationResponse: { error: { message: 'User request limit reached', @@ -414,7 +415,7 @@ export const v0TestData = [ body: { output: { status: 400, - message: 'Capability or permissions issue.', + message: 'Some error in permission', destinationResponse: { error: { message: 'Some error in permission', @@ -466,7 +467,8 @@ export const v0TestData = [ body: { output: { status: 500, - message: 'Unhandled random error', + message: + '{"message":"Unhandled random error","type":"RandomException","code":5,"error_subcode":12,"fbtrace_id":"facebook_px_trace_id_10"}', destinationResponse: { error: { message: 'Unhandled random error', @@ -488,6 +490,66 @@ export const v0TestData = [ }, }, + { + name: 'facebook_pixel', + description: 'Test 10: should handle error with code: 100 & subcode: 2804009', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + body: { + XML: {}, + FORM: testFormData, + JSON: {}, + JSON_ARRAY: {}, + }, + type: 'REST', + files: {}, + method: 'POST', + userId: '', + headers: {}, + version: '1', + endpoint: `https://graph.facebook.com/${VERSION}/12345678912804009/events?access_token=2804009_valid_access_token`, + params: { + destination: 'facebook_pixel', + }, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 400, + body: { + output: { + status: 400, + message: + 'Your purchase event doesn’t include a value parameter. Enter a value. For example: 1.99', + destinationResponse: { + error: { + message: 'Invalid parameter', + type: 'OAuthException', + code: 100, + error_user_msg: + 'Your purchase event doesn’t include a value parameter. Enter a value. For example: 1.99', + error_user_title: 'Missing Value for Purchase Event', + error_subcode: 2804009, + is_transient: false, + fbtrace_id: 'AP4G-xxxxxxxx', + }, + status: 400, + }, + statTags: { + ...statTags, + errorType: 'aborted', + }, + }, + }, + }, + }, + }, { name: 'facebook_pixel', description: 'Test 9: should handle error with code: 21009', diff --git a/test/integrations/destinations/facebook_pixel/dataDelivery/oauth.ts b/test/integrations/destinations/facebook_pixel/dataDelivery/oauth.ts index c6d938c627..bb4fd582f0 100644 --- a/test/integrations/destinations/facebook_pixel/dataDelivery/oauth.ts +++ b/test/integrations/destinations/facebook_pixel/dataDelivery/oauth.ts @@ -28,11 +28,11 @@ export const oauthScenariosV1: ProxyV1TestData[] = [ body: { output: { status: 400, - message: 'Capability or permissions issue.', + message: 'Some error in permission', statTags, response: [ { - error: 'Capability or permissions issue.', + error: 'Some error in permission', statusCode: 400, metadata: generateMetadata(1), }, diff --git a/test/integrations/destinations/facebook_pixel/dataDelivery/other.ts b/test/integrations/destinations/facebook_pixel/dataDelivery/other.ts index e25cc8e07c..154c6f75ad 100644 --- a/test/integrations/destinations/facebook_pixel/dataDelivery/other.ts +++ b/test/integrations/destinations/facebook_pixel/dataDelivery/other.ts @@ -31,14 +31,14 @@ export const otherScenariosV1: ProxyV1TestData[] = [ body: { output: { status: 429, - message: 'API User Too Many Calls', + message: 'User request limit reached', statTags: { ...statTags, errorType: 'throttled', }, response: [ { - error: 'API User Too Many Calls', + error: 'User request limit reached', statusCode: 429, metadata: generateMetadata(1), }, @@ -72,7 +72,8 @@ export const otherScenariosV1: ProxyV1TestData[] = [ body: { output: { status: 500, - message: 'Unhandled random error', + message: + '{"message":"Unhandled random error","type":"RandomException","code":5,"error_subcode":12,"fbtrace_id":"facebook_px_trace_id_10"}', statTags: { ...statTags, errorType: 'retryable', @@ -80,7 +81,8 @@ export const otherScenariosV1: ProxyV1TestData[] = [ }, response: [ { - error: 'Unhandled random error', + error: + '{"message":"Unhandled random error","type":"RandomException","code":5,"error_subcode":12,"fbtrace_id":"facebook_px_trace_id_10"}', statusCode: 500, metadata: generateMetadata(1), }, diff --git a/test/integrations/destinations/facebook_pixel/network.ts b/test/integrations/destinations/facebook_pixel/network.ts index 411d36cf19..a6ff50623b 100644 --- a/test/integrations/destinations/facebook_pixel/network.ts +++ b/test/integrations/destinations/facebook_pixel/network.ts @@ -15,6 +15,7 @@ export const networkCallsData = [ data: { error: { message: 'The access token could not be decrypted', + error_user_msg: 'The access token could not be decrypted', type: 'OAuthException', code: 190, fbtrace_id: 'fbpixel_trace_id', @@ -208,4 +209,29 @@ export const networkCallsData = [ statusText: 'OK', }, }, + { + httpReq: { + url: `https://graph.facebook.com/${VERSION}/12345678912804009/events?access_token=2804009_valid_access_token`, + data: getFormData(testFormData).toString(), + params: { destination: 'facebook_pixel' }, + headers: { 'User-Agent': 'RudderLabs' }, + method: 'POST', + }, + httpRes: { + status: 400, + data: { + error: { + code: 100, + error_subcode: 2804009, + error_user_msg: + 'Your purchase event doesn’t include a value parameter. Enter a value. For example: 1.99', + error_user_title: 'Missing Value for Purchase Event', + fbtrace_id: 'AP4G-xxxxxxxx', + is_transient: false, + message: 'Invalid parameter', + type: 'OAuthException', + }, + }, + }, + }, ]; diff --git a/test/integrations/destinations/fb/dataDelivery/data.ts b/test/integrations/destinations/fb/dataDelivery/data.ts index 9ee19af265..dfa5dbc65e 100644 --- a/test/integrations/destinations/fb/dataDelivery/data.ts +++ b/test/integrations/destinations/fb/dataDelivery/data.ts @@ -59,6 +59,7 @@ export const existingTestData = [ message: 'Invalid OAuth 2.0 access token', destinationResponse: { error: { + error_user_msg: 'Invalid OAuth 2.0 access token', code: 190, fbtrace_id: 'fbpixel_trace_id', message: 'The access token could not be decrypted', @@ -274,7 +275,7 @@ export const existingTestData = [ body: { output: { status: 429, - message: 'API User Too Many Calls', + message: 'User request limit reached', destinationResponse: { error: { message: 'User request limit reached', diff --git a/test/integrations/destinations/fb/dataDelivery/other.ts b/test/integrations/destinations/fb/dataDelivery/other.ts index 9ac3f14fb5..36d3e45f53 100644 --- a/test/integrations/destinations/fb/dataDelivery/other.ts +++ b/test/integrations/destinations/fb/dataDelivery/other.ts @@ -31,14 +31,14 @@ export const otherScenariosV1: ProxyV1TestData[] = [ body: { output: { status: 429, - message: 'API User Too Many Calls', + message: 'User request limit reached', statTags: { ...statTags, errorType: 'throttled', }, response: [ { - error: 'API User Too Many Calls', + error: 'User request limit reached', statusCode: 429, metadata: generateMetadata(1), }, diff --git a/test/integrations/destinations/fb/network.ts b/test/integrations/destinations/fb/network.ts index 31bbaf0b6e..1aed48136c 100644 --- a/test/integrations/destinations/fb/network.ts +++ b/test/integrations/destinations/fb/network.ts @@ -30,6 +30,7 @@ export const networkCallsData = [ data: { error: { message: 'The access token could not be decrypted', + error_user_msg: 'Invalid OAuth 2.0 access token', type: 'OAuthException', code: 190, fbtrace_id: 'fbpixel_trace_id', diff --git a/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts b/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts index b41c656d9f..cd440aaa37 100644 --- a/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts +++ b/test/integrations/destinations/fb_custom_audience/dataDelivery/data.ts @@ -623,6 +623,8 @@ export const existingTestData = [ fbtrace_id: 'A3b8C6PpI-kdIOwPwV4PANi', message: 'Error validating access token: Session has expired on Tuesday, 01-Aug-23 10:12:14 PDT. The current time is Sunday, 28-Jan-24 16:01:17 PST.', + error_user_msg: + 'Error validating access token: Session has expired on Tuesday, 01-Aug-23 10:12:14 PDT. The current time is Sunday, 28-Jan-24 16:01:17 PST.', type: 'OAuthException', }, status: 400, diff --git a/test/integrations/destinations/fb_custom_audience/network.ts b/test/integrations/destinations/fb_custom_audience/network.ts index 369c27afa9..ba14d537ad 100644 --- a/test/integrations/destinations/fb_custom_audience/network.ts +++ b/test/integrations/destinations/fb_custom_audience/network.ts @@ -514,6 +514,8 @@ export const networkCallsData = [ error: { message: 'Error validating access token: Session has expired on Tuesday, 01-Aug-23 10:12:14 PDT. The current time is Sunday, 28-Jan-24 16:01:17 PST.', + error_user_msg: + 'Error validating access token: Session has expired on Tuesday, 01-Aug-23 10:12:14 PDT. The current time is Sunday, 28-Jan-24 16:01:17 PST.', type: 'OAuthException', code: 190, error_subcode: 463,