Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
A 3D digital envelope icon representing a redirected approval flow email notification
Flow

Fixing Null Variables in Salesforce Approval Flow Emails

When an approval request is reassigned, email templates often return null values for merge fields. Here is how formula fields, Flow and Invocable Apex keep your notifications accurate.

The short answer

Approval email merge fields go null after a reassignment because the alert's context is bound to ProcessInstanceStep, and reassigning shifts the relationship between requestor, record and approver. Notify from a Record-Triggered Flow on ProcessInstanceWorkitem instead, or use proxy formula fields on the record.

Key takeaways Move off legacy email templates and notify from Flow, where you control the execution context. Approval Process email alerts are bound to the ProcessInstance lifecycle, so when the context changes the template can fail. Decouple the email template from Approval Process variables using record-level formula fields that resolve data consistently. When Flow runs out of road, a small Apex class that fetches the exact record relationships you need returns values instead of nulls.

The problem: why reassignment breaks merge fields

Approval Processes do plenty of work, but they carry a specific blind spot around context, and the null variable issue is where it shows up. Change an approver, by hand or from an automated process, and the email template the approval process fires populates its merge fields with nothing at all.

The reason is that the email alert's context is tied to the ProcessInstanceStep object. Reassign a record and the relationship between the original requestor, the record and the new target approver shifts, so standard merge fields like {!ApprovalRequest.Comments} resolve to null or show stale data. Three patterns get you around the limitation.

Strategy 1: moving from email alerts to flow-driven notifications

The sturdiest fix is to stop using native Approval Process Email Alerts and send the notification from Flow instead. Native alerts carry almost no logic. A Flow-based notification can re-query the record state at the moment it executes, which is the whole point.

The "after-update" approach

Build a Record-Triggered Flow on the ProcessInstanceWorkitem object, which represents a pending approval request, instead of leaning on the standard approval email template.

  1. Trigger the flow when a record is updated.
  2. Filter for ProcessInstanceWorkitem records where ActorId has changed.
  3. Send the message with the Send Custom Notification or Send Email action inside the Flow.

Building it this way hands you ActorId, the new approver, immediately, so you can fetch their User profile data and assemble an email body that has actual values in it.

Strategy 2: invocable apex to capture context

When the logic runs past what Flow will do for you, say parsing deep relationship fields that keep coming back null, Invocable Apex earns its keep. Apex lets you run the SOQL yourself and confirm you have the right data before anyone constructs an email out of it.

Here is a simple pattern for an Invocable method to fetch valid approver context:

public class ApprovalContextHandler {
    @InvocableMethod(label='Get Valid Approver Info')
    public static List<String> getApproverDetails(List<Id> workItemIds) {
        List<ProcessInstanceWorkitem> items = [SELECT Actor.Name, ProcessInstance.TargetObjectId 
                                               FROM ProcessInstanceWorkitem 
                                               WHERE Id IN :workItemIds];
        // Process logic here to ensure variables aren't null
        return new List<String>{ items[0].Actor.Name };
    }
}

Pass the WorkItemId into an Invocable method and you get a clean query. The approval process may forget the context during the redirect. Your code does not.

Strategy 3: the formula field fallback

The blunt option is often the one that survives. If your email template pulls data from the record being approved, stay away from {!ApprovalRequest.FieldName} syntax, which is volatile during reassignments.

Build proxy formula fields on the object being approved instead. Create one called Current_Approver_Name__c, have it use the Approver__r.Name field when that is populated, and fall back to a custom metadata setting or a related lookup when it is not. The template then references {!MyObject__c.Current_Approver_Name__c} and reads the record's current state rather than the volatile state of the Approval Instance.

Troubleshooting checklist for nulls

When a notification arrives with blanks in it, work down in this order.

Check the trigger order first. If your email alert fires before ActorId is updated in the database, the variable is null and nothing about your template is wrong. A Pause element in the Flow gives the database time to commit the new assignment.

Then validate field level security. A variable can hold a value and still arrive empty: if the user triggering the email, or the Automated Process User, lacks FLS on that specific field, Salesforce returns null to prevent data leakage. I have seen teams rebuild a template twice before anyone checks this one.

Then audit the ProcessInstance. Pull the ProcessInstanceWorkitem history in Query Editor. If OriginalActorId and ActorId are identical, the reassignment logic itself never ran, and the null is downstream of that.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment