[SalesForce] How to reference cross object field in Process builder and not allow for null values to not prompt error

So in a custom object in process builder, I'm trying to use a formula to populate the AccountBillingCity__c in the custom object using values from Account object, standard field BillingCity.

So I use the formula :

IF(NOT(ISBLANK([obj__c].Account__c.BillingCity)) ,
[obj__c].Account__c.BillingCity,
'<<ACCOUNT BILLING City>>')

Where I want to populate <> if the value in Account.BillingCity is null, otherwise reference the whole value into the obj__c.

But I still get emailed the process builder error :

Error element myRule_1_A1 (FlowRecordUpdate).
This error occurred when the flow tried to update records: The flow failed to access the value for myVariable_current.Account__r.BillingCity because it hasn't been set or assigned.. You can look up ExceptionCode values in the SOAP API Developer Guide.

UPDATE RECORDS: myRule_1_A1
Find all obj__c records where:
Id Equals {!myVariable_current.Id} (a1F0w0000000SgvEAE)
Update the records’ field values.
AccountBillingCity__c = {!formula_2_myRule_1_A1_4910200535} ()

Any ideas how to get around this?


UPDATE

To show where I implemented in PB

enter image description here

Best Answer

You need to take advantage of short-circuit evaluation to check for a null relationship earlier in the evaluation of the expression than the traversal of the relationship.

I wrote an article about how this works several years ago. Here's a quick summary of how it works in Process Builder.

Dereferencing a null field in a Process Builder condition or formula always results in an exception. Fortunately, Boolean operators and functions (AND and OR, including the implicit logical operations used in condition-based triggers) in the Process Builder context perform short-circuit evaluation. In other words, references across the lookup relationship can be guarded by checks against null lookups earlier in the evaluation order such that evaluation will stop before reaching the cross-object relationship, avoiding an exception. The evaluation order is left-to-right for the AND() and OR() functions and the && and || operators, and top-to-bottom for condition lists.

To apply this to your example,

IF(NOT(ISBLANK([obj__c].Account__c.BillingCity)) , 
      [obj__c].Account__c.BillingCity,
       '<<ACCOUNT BILLING City>>')

would become

IF(
    AND(
        NOT(ISBLANK([obj__c].Account__c)),
        NOT(ISBLANK([obj__c].Account__c.BillingCity))
    ), 
    [obj__c].Account__c.BillingCity,
    '<<ACCOUNT BILLING City>>'
)

The NOT(ISBLANK([obj__c].Account__c)) clause gets evaluated first, so if the relationship is null, it won't evaluate the cross-object reference.