I have a cloudpage which serves the purpose of ejecting records from existing journey(s). The credentials are stored in a BU Package DE, so are the records in an ejection DE. Since the exit contact api has a limit of 50 records per call, I am trying to batch it.
For some reason I am getting the Error Fetching Records: Unable to retrieve security descriptor for this frame while batching records error when I first tried batching in small quantities(just 2 records per batch)
I have been trying to figure out for the whole day what is causing this but am unable to come to a conclusion. I wrote a lot of log statements but still am unable to figure out whats causing this error [UPDATE] I am getting a new error:
Updated Code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Response Page</title> </head> <body> <div> <h1>Response</h1> <div> %%[ SET @rows = LookupRows("BU_PACKAGE_DETAILS_DE", "ACCOUNT_MID", "100029102") IF RowCount(@rows) > 0 THEN SET @clientId = Field(Row(@rows, 1), "CLIENT_ID") SET @clientSecret = Field(Row(@rows, 1), "CLIENT_SECRET") SET @accountId = Field(Row(@rows, 1), "ACCOUNT_MID") ELSE SET @clientId = "Not Found" SET @clientSecret = "Not Found" SET @accountId = "Not Found" ENDIF ]%% <script runat="server"> Platform.Load("Core", "1.1.1"); var clientId = Platform.Variable.GetValue("@clientId"); var clientSecret = Platform.Variable.GetValue("@clientSecret"); var accountId = Platform.Variable.GetValue("@accountId"); var batchSize = 2; // Process records in batches of 2 var batchNumber = 1; var continueProcessing = true; try { // Step 1: Retrieve Access Token Write("Step 1: Retrieving Access Token<br>"); var accessToken = getAccessToken(clientId, clientSecret, accountId); if (!accessToken) { throw new Error("Access token not retrieved"); } Write("Access Token: " + accessToken + "<br>"); while (continueProcessing) { Write("Entering while loop for batch number: " + batchNumber + "<br>"); try { // Step 2: Fetch records from Data Extension Write("Step 2: Fetching records from Data Extension<br>"); var records = Platform.Function.LookupOrderedRows("EJECTION_DE", batchSize, "RANK ASC", "PROCESSED_STATUS", "false"); Write("Records Retrieved: " + Platform.Function.Stringify(records) + "<br>"); if (records && records.length > 0) { var payload = []; for (var i = 0; i < records.length; i++) { var record = records[i]; var contactKey = record.PATIENT_COMPOSITE_KEY; var journeyDefinitionKey = record.JOURNEY_DEFINITION_KEY; Write("Processing Record " + i + ": ContactKey - " + contactKey + ", DefinitionKey - " + journeyDefinitionKey + "<br>"); payload.push({ "ContactKey": contactKey, "DefinitionKey": journeyDefinitionKey }); } Write("Batch Number: " + batchNumber + "<br>"); Write("Payload: " + Platform.Function.Stringify(payload) + "<br>"); var response = makeApiCall(accessToken, payload); Write("API Call Response Status Code: " + (response ? response.statusCode : "No Response") + "<br>"); Write("API Call Response: " + Platform.Function.Stringify(response) + "<br>"); if (response && (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 202)) { Write("API call to exit contacts from journey was successful.<br>"); for (var j = 0; j < records.length; j++) { var updateRecord = records[j]; Write("Updating Record " + j + ": Rank - " + updateRecord.RANK + "<br>"); var updateStatus = Platform.Function.UpdateData("EJECTION_DE", ["RANK"], [updateRecord.RANK], ["PROCESSED_STATUS", "TEST_RESPONSE_STATUS", "TEST_BATCH_NUMBER"], ["true", response.statusCode, batchNumber]); Write("Update Status: " + updateStatus + "<br>"); } } else { Write("Failed to exit contacts from journey. Status Code: " + (response ? response.statusCode : "No Response") + "<br>"); } batchNumber++; } else { continueProcessing = false; Write("No more records to process.<br>"); } } catch (fetchError) { Write("Error Fetching Records: " + fetchError.message + "<br>"); Write("Stack Trace: " + fetchError.stack + "<br>"); continueProcessing = false; } } } catch (ex) { Write("Error: " + ex.message + "<br>"); Write("Stack Trace: " + ex.stack + "<br>"); } function getAccessToken(clientId, clientSecret, accountId) { try { var authEndpoint = "https://REDACTED.auth.marketingcloudapis.com/v2/token"; var authPayload = Platform.Function.Stringify({ grant_type: "client_credentials", client_id: clientId, client_secret: clientSecret, account_id: accountId }); var authResponse = HTTP.Post(authEndpoint, "application/json", authPayload); Write("Auth Response: " + authResponse.StatusCode + "<br>"); if (authResponse.StatusCode === 200) { var authData = Platform.Function.ParseJSON(authResponse.Response[0]); return authData.access_token; } else { throw new Error("Failed to retrieve access token. Status Code: " + authResponse.StatusCode); } } catch (e) { Write("Error in getAccessToken: " + e.message + "<br>"); Write("Stack Trace: " + e.stack + "<br>"); return null; } } function makeApiCall(accessToken, payload) { try { var endpointUrl = "https://REDACTED.rest.marketingcloudapis.com/interaction/v1/interactions/contactexit"; var req = new Script.Util.HttpRequest(endpointUrl); req.retries = 3; req.continueOnError = true; req.setHeader("Authorization", "Bearer " + accessToken); req.method = "POST"; req.contentType = "application/json; charset=utf-8"; req.postData = Platform.Function.Stringify(payload); Write("Sending API Request...<br>"); var response = req.send(); if (response) { Write("API Response Status Code: " + response.statusCode + "<br>"); Write("API Response Content: " + response.content + "<br>"); } else { Write("No response from API call.<br>"); } if (response.contentType === "application/json") { return Platform.Function.ParseJSON(response.content); } else { return response.content; } } catch (e) { Write("Error in makeApiCall: " + e.message + "<br>"); Write("Stack Trace: " + e.stack + "<br>"); return null; } } </script> </div> </div> </body> </html> UPDATED ERROR OUTPUT:
Step 1: Retrieving Access Token Auth Response: 200 Access Token: REDACTED Step 2: Fetching records from Data Extension Records Retrieved: [{"_CustomObjectKey":114,"RANK":1",CreatedDate":"2024-06-12T05:20:20.600","TEST_RESPONSE_STATUS":"","TEST_BATCH_NUMBER":""}, {"SIMILARLY SECOND RECORD}] Error Fetching Records: Use of Common Language Runtime (CLR) is not allowed Stack Trace: undefined ARCHIVED OLD code:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Response Page</title> </head> <body> Response <div class="layout layout-canvas-g"> <div class="section"> <div class="columns col1"> <div data-type="slot" data-key="col1"> %%[ SET @rows = LookupRows("BU_PACKAGE_DETAILS_DE", "ACCOUNT_MID", "100029102") IF RowCount(@rows) > 0 THEN SET @clientId = Field(Row(@rows, 1), "CLIENT_ID") SET @clientSecret = Field(Row(@rows, 1), "CLIENT_SECRET") SET @accountId = Field(Row(@rows, 1), "ACCOUNT_MID") ELSE SET @clientId = "Not Found" SET @clientSecret = "Not Found" SET @accountId = "Not Found" ENDIF ]%% <script runat="server"> Platform.Load("Core", "1.1.1"); var clientId = Platform.Variable.GetValue("@clientId"); var clientSecret = Platform.Variable.GetValue("@clientSecret"); var accountId = Platform.Variable.GetValue("@accountId"); var batchSize = 2; // Process records in batches of 2 var batchNumber = 1; var continueProcessing = true; try { // Step 1: Retrieve Access Token Write("Step 1: Retrieving Access Token<br>"); var accessToken = getAccessToken(clientId, clientSecret, accountId); if (!accessToken) { throw new Error("Access token not retrieved"); } Write("Access Token: " + accessToken + "<br>"); while (continueProcessing) { // Step 2: Fetch records from Data Extension Write("Step 2: Fetching records from Data Extension<br>"); try { var records = Platform.Function.LookupOrderedRows("EJECTION_DE", batchSize, "RANK ASC", "PROCESSED_STATUS", "false"); Write("Records Retrieved: " + Platform.Function.Stringify(records) + "<br>"); if (Platform.Function.RowCount(records) > 0) { var payload = []; for (var i = 0; i < records.length; i++) { var record = records[i]; var contactKey = record.PATIENT_COMPOSITE_KEY; var journeyDefinitionKey = record.JOURNEY_DEFINITION_KEY; payload.push({ "ContactKey": contactKey, "DefinitionKey": journeyDefinitionKey }); } // Log the payload to ensure it is correctly formatted Write("Batch Number: " + batchNumber + "<br>"); Write("Payload: " + Platform.Function.Stringify(payload) + "<br>"); var response = makeApiCall(accessToken, payload); Write("API Call Response: " + Platform.Function.Stringify(response) + "<br>"); if (response && (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 202)) { Write("API call to exit contacts from journey was successful.<br>"); for (var j = 0; j < records.length; j++) { var updateRecord = records[j]; Platform.Function.UpdateData("EJECTION_DE", ["RANK"], [updateRecord.RANK], ["PROCESSED_STATUS", "TEST_RESPONSE_STATUS", "TEST_BATCH_NUMBER"], ["true", response.statusCode, batchNumber]); } } else { Write("Failed to exit contacts from journey. Status Code: " + (response ? response.statusCode : "No Response") + "<br>"); } batchNumber++; } else { continueProcessing = false; Write("No more records to process.<br>"); } } catch (fetchError) { Write("Error Fetching Records: " + fetchError.message + "<br>"); Write("Stack Trace: " + fetchError.stack + "<br>"); continueProcessing = false; } } } catch (ex) { Write("Error: " + ex.message + "<br>"); Write("Stack Trace: " + ex.stack + "<br>"); } function getAccessToken(clientId, clientSecret, accountId) { try { var authEndpoint = "https://SFMC URL.auth.marketingcloudapis.com/v2/token"; var authPayload = Platform.Function.Stringify({ grant_type: "client_credentials", client_id: clientId, client_secret: clientSecret, account_id: accountId }); var authResponse = HTTP.Post(authEndpoint, "application/json", authPayload); Write("Auth Response: " + authResponse.StatusCode + "<br>"); if (authResponse.StatusCode === 200) { var authData = Platform.Function.ParseJSON(authResponse.Response[0]); return authData.access_token; } else { throw new Error("Failed to retrieve access token. Status Code: " + authResponse.StatusCode); } } catch (e) { Write("Error in getAccessToken: " + e.message + "<br>"); Write("Stack Trace: " + e.stack + "<br>"); return null; } } function makeApiCall(accessToken, payload) { try { var endpointUrl = "https://SFMC URL.rest.marketingcloudapis.com/interaction/v1/interactions/contactexit"; var req = new Script.Util.HttpRequest(endpointUrl); req.retries = 3; req.continueOnError = true; req.setHeader("Authorization", "Bearer " + accessToken); req.method = "POST"; req.contentType = "application/json; charset=utf-8"; req.postData = Platform.Function.Stringify(payload); var response = req.send(); if (response.contentType === "application/json") { return Platform.Function.ParseJSON(response.content); } else { return response.content; } } catch (e) { Write("Error in makeApiCall: " + e.message + "<br>"); Write("Stack Trace: " + e.stack + "<br>"); return null; } } </script> </div> </div> </div> </div> </body> </html> Here is the output response:
Step 1: Retrieving Access Token Auth Response: 200 Access Token: REDACTED Step 2: Fetching records from Data Extension Records Retrieved: [{"_CustomObjectKey":114,"RANK":1",CreatedDate":"2024-06-12T05:20:20.600","TEST_RESPONSE_STATUS":"","TEST_BATCH_NUMBER":""}, {"SIMILARLY SECOND RECORD}] Error Fetching Records: Unable to retrieve security descriptor for this frame. Stack Trace: undefined NOTE: The code seems to work when I hardcode one record for ejection
PLEASE HELP ME OUT!