APIs & Integrations

CaBisc
Participant

Node.js script error with log 4KB limit

Hello, 

I have the following script in a custom code block of Hubspot workflows that returns the following error: 

Code:

const firstNameProperty = 'firstname';
const lastNameProperty = 'lastname';
const companyProperty = 'company';
const emailProperty = 'email';

const hubspot = require('@hubspot/api-client');
const email_providers = ['gmail.com', 'yahoo.com', 'yahoo.co.uk', 'outlook.com', 'icloud.com', 'hotmail.com', 'hotmail.co.uk']

// check if contact has a professional email or not
function contactHasProfessionalEmail(contact) {
  for (let email of email_providers) {
    if (contact.email.includes(email)) {
      return false
    }
  }
  return true
}

// merge subject contact on target contact
async function mergeContacts(subject, target, hubspotClient) {          
  const mergeResult = await hubspotClient
  .apiRequest({
    method: 'POST',
    path: `/contacts/v1/contact/merge-vids/${target.hs_object_id}`,
    body: {
      vidToMerge: subject.hs_object_id
    }
  })
  
  if (mergeResult.status === 200) {
    console.log(`contact: ${subject.hs_object_id} has been merged on contact: ${target.hs_object_id}`)
  } else {
    console.log('something went wrong with the merging!')
  }
  
  return mergeResult;
}

exports.main = async (event, callback) => {
  // Make sure to add your API key under "Secrets" above.
  const hubspotClient = new hubspot.Client({
    accessToken: process.env.api_key
  });

  try {
    const contact = await hubspotClient.crm.contacts.basicApi.getById(event.object.objectId, [firstNameProperty, lastNameProperty, companyProperty, emailProperty])
    const firstNameValue = contact.properties[firstNameProperty];
    const lastNameValue = contact.properties[lastNameProperty];
    const companyValue = contact.properties[companyProperty];
    const emailValue = contact.properties[emailProperty];
    
    console.log(`Looking for duplicates based on ${firstNameProperty} = ${firstNameValue}, ${lastNameProperty} = ${lastNameValue}, ${companyProperty} = ${companyValue}, ${emailProperty} = ${emailValue}`);
    
    const properties = ['firstname', 'lastname', 'email', 'company', 'last_activity_date']
    const potentialDuplicatesRaw = await hubspotClient.crm.contacts.searchApi
        .doSearch({
          filterGroups: [
            {
              filters: [
                {
                  propertyName: firstNameProperty,
                  operator: 'EQ',
                  value: firstNameValue
                },
                {
                  propertyName: lastNameProperty,
                  operator: 'EQ',
                  value: lastNameValue
                },
                {
                  propertyName: companyProperty,
                  operator: 'EQ',
                  value: companyValue
                }
              ]
            }
          ],
          properties
        })
    
    const potentialDuplicates = potentialDuplicatesRaw.results.map(el => el.properties)
    console.log(potentialDuplicates)
    
    // do nothing if no duplicate or abort if more than 2 similar contacts
    if (potentialDuplicates.length <= 1) {
      console.log('No matching contact, nothing to merge');
      return;
    } else if (potentialDuplicates.length > 2) {
      console.log(`Found multiple potential contacts to merge`);
    }
    
    const firstContact = potentialDuplicates[0]
    const secondContact = potentialDuplicates[1]
    
    // merge the contact with the personal email address on the one that has a professional email
    if (contactHasProfessionalEmail(firstContact) && !contactHasProfessionalEmail(secondContact)) {
      mergeContacts(secondContact, firstContact, hubspotClient);
      return;
    } else if (!contactHasProfessionalEmail(firstContact) && contactHasProfessionalEmail(secondContact)) {
      mergeContacts(firstContact, secondContact, hubspotClient);
      return;
    }
	
    // if no professional email exists, merge on the one that has the most recent activity
    const mostRecentContact = potentialDuplicates.reduce((acc, cur) => {
      if (!acc || new Date(cur.last_activity_date) > new Date(acc.last_activity_date)) {
        return cur;
      } else {
        return acc;
      }
	}, null);
    const oldestContact = potentialDuplicates.find(item => item.hs_object_id !== mostRecentContact.hs_object_id)
    
    mergeContacts(oldestContact, mostRecentContact, hubspotClient)
    
  } catch (err) {
    console.error(err);
    // We will automatically retry when the code fails because of a rate limiting error from the HubSpot API.
    throw err;
  }
}



Error: 

WARNING: The logs for this function have exceeded the 4KB limit.
...
lose\",\"content-length\":\"186\",\"content-type\":\"application/json;charset=utf-8\",\"date\":\"Thu, 07 Sep 2023 08:46:00 GMT\",\"nel\":\"{\\\"success_fraction\\\":0.01,\\\"report_to\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"report-to\":\"{\\\"endpoints\\\":[{\\\"url\\\":\\\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report\\\\/v3?s=G2ruUT6cS5B%2B4AGF6q3usCQk2DBSXDMJA5%2Fr2DmtZg23akJWIXL2Uqz3GWsgXUowsYcFNNg1wWtx4Fy69pZp1UVmbOV6b4ChPCZIbSyAPMs8cDXc7huyfcPI2kRT7JKd\\\"}],\\\"group\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"server\":\"cloudflare\",\"strict-transport-security\":\"max-age=31536000; includeSubDomains; preload\",\"vary\":\"origin, Accept-Encoding\",\"x-content-type-options\":\"nosniff\",\"x-envoy-upstream-service-time\":\"11\",\"x-evy-trace-listener\":\"listener_https\",\"x-evy-trace-route-configuration\":\"listener_https/all\",\"x-evy-trace-route-service-name\":\"envoyset-translator\",\"x-evy-trace-served-by-pod\":\"iad02/hubapi-td/envoy-proxy-6c94986c56-g952g\",\"x-evy-trace-virtual-host\":\"all\",\"x-hubspot-correlation-id\":\"ddb3e669-8978-4aaa-a779-9f2de2b89751\",\"x-hubspot-ratelimit-daily\":\"500000\",\"x-hubspot-ratelimit-daily-remaining\":\"499762\",\"x-request-id\":\"ddb3e669-8978-4aaa-a779-9f2de2b89751\",\"x-trace\":\"2BF1F14F04D22521D98A20DEA9E92C629741A8903D000000000000000000\"}","    at SearchApiResponseProcessor.<anonymous> (/opt/nodejs/node_modules/@hubspot/api-client/lib/codegen/crm/contacts/apis/SearchApi.js:63:23)","    at Generator.next (<anonymous>)","    at fulfilled (/opt/nodejs/node_modules/@hubspot/api-client/lib/codegen/crm/contacts/apis/SearchApi.js:5:58)","    at processTicksAndRejections (node:internal/process/task_queues:96:5)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: HTTP-Code: 400","Message: An error occurred.","Body: {\"status\":\"error\",\"message\":\"Invalid input JSON on line 1, column 205: operator EQ requires a value\",\"correlationId\":\"ddb3e669-8978-4aaa-a779-9f2de2b89751\",\"category\":\"VALIDATION_ERROR\"}","Headers: {\"access-control-allow-credentials\":\"false\",\"cf-cache-status\":\"DYNAMIC\",\"cf-ray\":\"802dadc42bdc2012-IAD\",\"connection\":\"close\",\"content-length\":\"186\",\"content-type\":\"application/json;charset=utf-8\",\"date\":\"Thu, 07 Sep 2023 08:46:00 GMT\",\"nel\":\"{\\\"success_fraction\\\":0.01,\\\"report_to\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"report-to\":\"{\\\"endpoints\\\":[{\\\"url\\\":\\\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report\\\\/v3?s=G2ruUT6cS5B%2B4AGF6q3usCQk2DBSXDMJA5%2Fr2DmtZg23akJWIXL2Uqz3GWsgXUowsYcFNNg1wWtx4Fy69pZp1UVmbOV6b4ChPCZIbSyAPMs8cDXc7huyfcPI2kRT7JKd\\\"}],\\\"group\\\":\\\"cf-nel\\\",\\\"max_age\\\":604800}\",\"server\":\"cloudflare\",\"strict-transport-security\":\"max-age=31536000; includeSubDomains; preload\",\"vary\":\"origin, Accept-Encoding\",\"x-content-type-options\":\"nosniff\",\"x-envoy-upstream-service-time\":\"11\",\"x-evy-trace-listener\":\"listener_https\",\"x-evy-trace-route-configuration\":\"listener_https/all\",\"x-evy-trace-route-service-name\":\"envoyset-translator\",\"x-evy-trace-served-by-pod\":\"iad02/hubapi-td/envoy-proxy-6c94986c56-g952g\",\"x-evy-trace-virtual-host\":\"all\",\"x-hubspot-correlation-id\":\"ddb3e669-8978-4aaa-a779-9f2de2b89751\",\"x-hubspot-ratelimit-daily\":\"500000\",\"x-hubspot-ratelimit-daily-remaining\":\"499762\",\"x-request-id\":\"ddb3e669-8978-4aaa-a779-9f2de2b89751\",\"x-trace\":\"2BF1F14F04D22521D98A20DEA9E92C629741A8903D000000000000000000\"}","    at process.<anonymous> (file:///var/runtime/index.mjs:1250:17)","    at process.emit (node:events:513:28)","    at emit (node:internal/process/promises:140:20)","    at processPromiseRejections (node:internal/process/promises:274:27)","    at processTicksAndRejections (node:internal/process/task_queues:97:32)"]}
Unknown application error occurred
Runtime.Unknown

Memory: 75/128 MB
Runtime: 1898.85 ms

 

Any idea on how to solve this?
Thanks!

0 Upvotes
2 Replies 2
CaBisc
Participant

Node.js script error with log 4KB limit

@Jaycee_Lewis Hello! This seems to have resolved the issue and the test contacts I used in the workflow where properly merged with duplicates that matched the criteria. 

However, the script is supposed to set the work email as primary email, and on the contacts I tested it did not work. Do you know what could be wrongly set up in the script or what I should edit to make sure it works properly?

Also, I was thinking of creating a list to spot potential duplicates and merge them. Do you have any other suggestion to spot duplicates and use it as a trigger in this workflow? I know that HS has a duplicate finder system, but it does not tag contacts as potential duplicates unfortunatly. Any way to leverage this to make it a trigger?

 

Thanks a lot!!

0 Upvotes
Jaycee_Lewis
Community Manager
Community Manager

Node.js script error with log 4KB limit

Hey, @CaBisc 👋 Thanks for your question! I spent some time staring at the error message you shared. Sadly, no magic eye type image appeared to me. But I did parse it down a bit. 

 

The error is complaining about an `EQ` filter not having a value. What's confusing is it's griping about Line 1. But the search API call you set up with filters is further down in your code. Why?

 

Which reminded me of the phrase, “When you hear hoofbeats behind you, don't expect to see a zebra.” 

 

So, let's try something. Can you add another check to your code? Something simple like this?

 

if (!firstNameValue || !lastNameValue || !companyValue) {
    console.error('One or more required values are missing!');
    return;
}

 

Right after 

 

const firstNameValue = contact.properties[firstNameProperty];
const lastNameValue = contact.properties[lastNameProperty];
const companyValue = contact.properties[companyProperty];
const emailValue = contact.properties[emailProperty];

 

 

What I am wondering is if, sometimes, there are cases where one or more of these properties are blank or null. And in those cases, the search API is irritated because it needs a value for those properties. 

 

Talk soon! — Jaycee


HubSpot’s AI-powered customer agent resolves up to 50% of customer queries instantly, with some customers reaching up to 90% resolution rates.
Learn More.


Did you know that the Community is available in other languages?
Join regional conversations by changing your language settings !
0 Upvotes