Straight answer: a flow threw “Attempt to de-reference a null object” because you used a field on a record variable that was never populated — almost always the output of a Get Records that found nothing, or a lookup traversal where the parent Id is blank. Flow will not warn you at design time. Add a Decision that tests the variable’s Id for null before any element touches its fields.
Why this reads differently in Flow than in Apex
In Apex the exception is a compile-honest runtime failure on an object reference you can see. In Flow there is no visible object — you have a record variable, and a formula or assignment quietly reaches through it. So the error text is identical but the diagnosis is completely different: you are looking for an empty Get Records, not a null pointer.
Flow also fails the whole interview. There is no partial completion, no catch by default, and a screen flow shows the user an unhandled-fault screen while a record-triggered flow rolls the save back and shows a generic error on the page.
Cause 1: Get Records found nothing
This is the overwhelming majority. A Get Records that matches no rows does not error — it returns an empty result and leaves the variable null. The next element that touches a field on it throws.
The fix is a Decision immediately after every Get Records:
- Outcome Found:
{!Get_Account}Id Is NullFalse - Default outcome: handle the miss: assign a default, skip the branch, or fault deliberately with a message that says what was not found.
Test the Id, not the whole variable and not a text field. A record variable’s Id is populated exactly when a record was returned, which makes it the reliable sentinel. Checking a text field fails when the record exists but the field is blank, which sends you down the wrong path with a confusing outcome.
When Get Records is configured to store all records rather than only the first, the output is a collection. A null check does not apply. Check the collection’s count instead, using an Assignment to a number variable or a Decision on the collection being empty.
Cause 2: traversing a lookup that is blank
A formula like {!$Record.Account.Owner.Email} throws the moment AccountId is null on the record being saved. Every hop in that chain is a place it can break, and an Opportunity with no Account is not an exotic case. It is what an import produces.
Guard the chain rather than the last hop:
IF( ISBLANK({!$Record.AccountId}),
'',
{!$Record.Account.Owner.Email} )
Or, better for a record-triggered flow, put AccountId is not null into the entry criteria so the flow never starts for records that cannot satisfy it. Entry criteria cost nothing when they fail. A started flow that faults costs the user their save.
Cause 3: a variable populated only on one branch
A Decision sets {!varContact} on the “existing customer” path and leaves it untouched on the other. Both paths then converge on an element that reads {!varContact.Email}. It works in every test anybody wrote, because everyone tested the branch that populates it.
Initialise variables with a default value where one makes sense, and where it does not, re-test for null after the convergence point. Convergence is where flows hide their bugs.
Cause 4: a subflow output that was never assigned
A subflow that ends on a path where its output variable is never set returns null to the parent, which then dereferences it. The parent flow’s designer usually has no idea the subflow has an early exit.
Treat subflow outputs exactly like Get Records outputs. Check them on return. A subflow’s contract is not enforced by anything, so it has to be enforced by the caller.
Diagnosing it from the fault
Turn on flow debug logging, or open the fault email, and look for the element name in the error. Flow names the element that threw, which tells you where: the question is always which variable, and the answer is nearly always the output of the nearest preceding Get Records.
In the Flow Builder debugger, run with “Show details of what’s executed” and step through. The variable panel shows null values explicitly, so you can see the exact element where the variable is still empty.
For record-triggered flows, debug with a real record that reproduces the condition rather than the happy-path one, and remember that the debugger’s behaviour with rollback can hide downstream effects.
Preventing it
- Every Get Records is followed by a null check. No exceptions. Make it a review rule, because it is mechanical and easy to enforce.
- Put required-field conditions in entry criteria rather than defending inside the flow.
- Add a Fault path on every element that can fault, pointing at a screen or a log record that says which element failed and on which record Id.
- Do not traverse more than one lookup hop in a formula without a guard. Each hop is a null waiting to happen.
- Name variables so their nullability is obvious —
varAccountOrNullis ugly and it prevents this bug.
Frequently asked
Why does the flow work in debug but fail in production?
You debugged with a record that has the lookup populated. Production has records that do not. Debug with the worst record you can find, not a representative one.
Does a Fault path fix the error?
It catches it, which is not the same thing. A fault path that shows a friendly message still means the work did not happen. Use fault paths for reporting and null checks for prevention.
Can I check a record variable for null directly?
Check its Id field with Is Null. That is the dependable test, and it works for both “no record returned” and “variable never assigned”.
What is the equivalent problem in a collection?
An empty collection is not null, so a null check passes and a loop simply does not execute, which is usually safe. The bug appears when you index into it or use a formula assuming a first element exists.
Does this roll back the record save?
In a record-triggered flow, an unhandled fault rolls back the whole transaction including the user’s save. That is why prevention matters more here than in a screen flow, where the user merely sees an error.
Reference: Flow Builder and Troubleshoot Flow Errors, Salesforce Help; Triggers and Order of Execution, Salesforce Apex Developer Guide.