---
title: "Flow formula problems, and why it works in a field"
url: "https://trailassembly.com/flow-formula-gotchas/"
topic: "Flow and Automation"
published: "2026-09-15T12:19:48+00:00"
updated: "2026-10-06T13:56:00+00:00"
---

# Flow formula problems, and why it works in a field

**Flow formulas look like field formulas and are not the same engine.** There is no “treat blank fields as zeroes” setting, so null poisons arithmetic silently. Relationship traversal works off `$Record` and not off a record variable you built yourself. And half the functions you rely on in a field formula, including PRIORVALUE and ISNEW, do not exist in Flow at all.

## Null is the first thing that will get you

A formula field on an object has a checkbox: treat blank fields as zeroes, or treat them as blanks. Flow has no such checkbox. A null number in an expression makes the whole expression null, and null is not zero, and it is not an error either. Your Decision quietly takes the default outcome.

Wrap anything that might be empty:

```apex
BLANKVALUE({!varDiscount}, 0) + BLANKVALUE({!varSurcharge}, 0)
```

For text, `ISBLANK` and `BLANKVALUE` both work. For numbers and dates, `NULLVALUE` does the same job. The habit worth building is defensive by default: if a number came from a [Get Records](https://trailassembly.com/flow-get-records-behaviour/), a screen input, or a [subflow](https://trailassembly.com/flow-subflow-variables/) output, assume it can be null, because all three regularly are. Touch a field on one without checking and the interview ends with [Attempt to de-reference a null object](https://trailassembly.com/flow-null-dereference/).

## Types do not convert themselves

The concatenation operator `&` only joins text. Joining a number to a string fails at save time with an unhelpful message about the formula’s return type. Wrap it:

```apex
"Order " & {!varOrderNumber} & " totals " & TEXT({!varAmount})
```

Picklists are the other conversion problem. When a comparison against a picklist refuses to save, wrap the reference in `TEXT()` and try again. Multi-select picklists hold one semicolon-joined string, so `Equals` against a single value never matches when the user picked two.

## Dates, date/times, and the time zone nobody mentioned

Subtracting one Date from another gives a whole number of days. Subtracting one DateTime from another gives a fractional number of days, so 6 hours comes back as 0.25. Mixing the two in one expression is the most common reason a “days since” formula returns something absurd.

`TODAY()` returns the [running user](https://trailassembly.com/dashboard-running-user/)‘s date. `NOW()` returns a DateTime. `DATEVALUE()` on a DateTime converts using GMT, not the user’s time zone, which means a record created at 8pm in Sydney can land on the previous day. If the answer must match what the user sees on screen, do the comparison on a Date field, not by converting a DateTime.

## Cross-object references are narrower than you expect

In a record-triggered flow, `$Record` lets you walk up to a parent: `{!$Record.Account.Owner.Email}` resolves without a Get Records. This is the single most useful thing in flow formulas and people underuse it.

It does not work the other way. There is no traversal down to child records, no equivalent of a roll-up, and no VLOOKUP. If you need a child value, query for it.

For a record variable you populated yourself with a Get Records, the safe assumption is that only the fields you actually stored are populated. Do not build logic that depends on a parent field appearing on a record you queried without asking for it. Query the parent explicitly, or store the field you need on the way past.

`$Record__Prior` is available in after-save flows and is null on insert. Comparing `{!$Record.StageName}` to `{!$Record__Prior.StageName}` is how you detect a change, since `ISCHANGED` and `PRIORVALUE` are not available to you here. A Decision also offers an **Is Changed** operator, which is cleaner for a simple case.

## Why a field formula fails when you paste it into Flow

Several reasons, and it is usually more than one:

- Functions that only make sense on a saved record are absent: ISNEW, PRIORVALUE, [ISCHANGED](https://trailassembly.com/flow-ischanged/), VLOOKUP, and the image and hyperlink helpers.

- Merge field syntax differs. A field formula writes `Account.Name`. A flow formula writes `{!$Record.Account.Name}` or `{!varAccount.Name}`.

- The blank-as-zero setting does not come with it.

- A flow formula has a declared return type set when you created the resource. A formula that returns text in a resource typed as Number fails validation with a message about the type, not about the logic.

## Frequently asked

**Why does my formula return the old value?** Formulas evaluate at the point of reference, not at flow start. If you referenced it before the Assignment that set the variable, you got the earlier state. Move the reference, or store the result in a variable.

**Does CASESAFEID exist in Flow?** Yes, and you need it whenever you compare an Id that came from a URL or a text field against a record Id, because 15-character and [18-character](https://trailassembly.com/invalid-id-15-vs-18/) Ids are not equal as strings.

**How do I see what a formula evaluated to?** Assign it to a variable temporarily. The debug panel shows variable values and assignment history. It does not show formula intermediates.

---

Source: https://trailassembly.com/flow-formula-gotchas/
Trail Assembly — independent Salesforce write-ups.
