Reference
Formula Checks
Detailed page. Use “On this page” to jump directly to the section you need.
Configure a Formula Check for a question Salesforce can answer from the current record and its parent records, such as “Does this Account have an Industry and an Annual Revenue?”
Reference
- This page explains every Formula setting, result, access rule, transaction limit, and failure path.
- For every field’s size, default, help text, and example, use the Check field reference.
For a common owner check, use Owner.IsActive on Account. On Lead, where Owner is polymorphic, use
Owner:User.IsActive when the rule applies to user-owned Leads and handle queue ownership through
applicability or a Query Check.
Required Formula settings
Section titled “Required Formula settings”| Setup field | API name | Requirement |
|---|---|---|
| Evaluation Type | EvaluationType__c | Verify with a formula: FORMULA |
| Pass Condition | PassConditionFormula__c | Required Boolean formula; true returns PASS, false returns FAIL |
| Display: Found Formula | DisplayFoundFormula__c | Optional display-only Found value |
| Display: Expected Formula | DisplayExpectedFormula__c | Optional display-only Expected value |
| Formula Result Type | FormulaResultType__c | Keep Automatic: AUTO; this Query-operand setting does not control Formula Checks |
Query and custom Apex fields are not used by a Formula Check. Applicability runs before the Pass
Condition and can return SKIPPED without running that formula.
For dependency-depth, numeric-null, timezone, currency, global-variable, and polymorphic boundaries, see Platform limitations and safe patterns.
For example:
AND(NOT(ISBLANK(Industry)), AnnualRevenue > 0)This formula returns PASS only when the Account has an Industry and Annual Revenue is greater than zero.
Formula context and syntax
Section titled “Formula context and syntax”- Write Salesforce formula syntax without a leading
=. - Enclose text literals in double quotes. A lone opening quote or an escaped final quote does not close a literal; correct the closing delimiter before running the Check. Malformed literal contents are redacted in planning findings.
- Reference current-record fields by API name, such as
AnnualRevenueorCustom_Score__c. - For a field owned by another installed package, preserve its complete API name, including the
namespace, such as
SBQQ__AssetQuantitiesCombined__c. Record Health Check resolves the name as authored and never retries an unqualified variant. - Traverse supported parent relationships, such as
Parent.Parent.AnnualRevenue. - Formula fields and roll-up summary fields can be used in the formula; Record Health Check evaluates their current values.
- When a referenced formula field depends on other fields, Record Health Check follows those field dependencies up to 10 levels while preparing the record query. Administrators do not have to list every field used inside the referenced formula field.
- A record formula cannot aggregate child collections. Use a Query Check or Apex when child records must be counted, summed, or grouped.
- Polymorphic relationships (
Owner,CreatedBy,LastModifiedBy,What,Who) can be disambiguated with Salesforce’s colon syntax,Relationship:SObjectType.Field, for exampleOwner:User.IsActive. Record Health Check recognizes this syntax when preparing the record query and validates the type segment against the object’s schema, so a mistyped type (or one that isn’t a real candidate for that relationship) is treated the same as any other unresolvable path rather than guessing. - Flat SOQL can load only fields exposed by Salesforce’s polymorphic
Namepseudo-entity. For example,What:Account.Nameis supported, while an Account-only field such asWhat:Account.Industryrequires a Query or Apex Check; it is omitted from Formula record loading so one unsupported field cannot invalidate the shared scope query. - Whether an owner relationship needs the colon segment is decided by the relationship’s
schema. The Account example uses
Owner.IsActive,Owner.FirstName, andOwner.LastName. For polymorphic owners that require an explicit type, useOwner:User.Field; a path that does not match the object’s schema can returnFIELD_NOT_RESOLVED. $User,$Profile,$Setup,$Permission, and other global merge references are never treated as record fields; a formula that reads$User.Idnever adds a bogusUser.Idpath to the record query. FormulaEval rejects these globals in record context, and Record Health Check returnsUNABLE_TO_EVALUATEwithINVALID_FORMULArather than producing an execution-user-dependent verdict. For a page-versus-automation incident, use the execution-context troubleshooting guide.
The Pass Condition must return a Checkbox value (true or false) and is evaluated as Boolean.
Display formulas can return Checkbox, Number, Date, Date/Time, or Text and probe their own result
type. Formula Result Type does not control either surface; it is used only by Query Checks that
calculate a comparison operand from Expected Value (Formula) or Value to find in the list
(formula).
Found and Expected values
Section titled “Found and Expected values”Display formulas never change PASS or FAIL.
- Found should show the value the Check observed.
- Expected should show the target used by the pass condition.
- Keep both formulas aligned with the values compared in Pass Condition.
- If Display: Expected Formula is blank, the card can show the default Passes when explanation.
- If Display: Found Formula is blank, no custom Found value is produced.
Ownership checks: Active User, Queue/Group, and QUERY vs Formula
Section titled “Ownership checks: Active User, Queue/Group, and QUERY vs Formula”“Owner is active” is a common Check, and it has two supported patterns with different behavior for non-User owners:
Example_Account_Owner_Active uses the Formula pattern on Account with Owner.IsActive.
Found shows the owner’s name and active/inactive status; Expected shows Active. Its formula
returns true for an active User and false for an inactive User. The Account example does not
model Queue ownership; the table below describes the explicitly typed polymorphic variant.
| Pattern | Example | Queue/Group owner | Missing/inaccessible User |
|---|---|---|---|
Formula Owner:User.IsActive | Custom Formula Check | UNABLE_TO_EVALUATE. FormulaEval cannot resolve a User-only path against a non-User owner, and a null formula result never becomes FAIL | UNABLE_TO_EVALUATE, for the same reason |
QUERY SELECT COUNT() FROM User WHERE Id = {!record.OwnerId} AND IsActive = true | Account_EU_OwnerIsActive | FAIL. A Queue/Group Id never matches a User row, so the count is 0 | FAIL. A missing, inaccessible, or genuinely inactive User row all produce the same 0 |
Neither pattern produces a false PASS for a non-User or
inactive owner. They differ in how they fail: the Formula path reports “I could not determine
this” (UNABLE_TO_EVALUATE), while the QUERY COUNT() pattern reports “this condition was not
satisfied” (FAIL) without distinguishing why the count was zero. Choose QUERY when you want a
same unable-to-evaluate outcome across Queue, inactive User, and missing User; choose Formula (after
Record Health Check loads the fields described in the polymorphic guidance above) when you want a Queue/Group owner treated as
“can’t tell,” not as “fails the check.”
Label Check titles, failure messages, and action copy “active User”, not “active owner,” unless
the Check is also designed to model Queue/Group ownership explicitly (for example with a dedicated
Queue-ratio Query Check). A COUNT() = 0 result alone does not distinguish an inactive User, a
Queue/Group owner, a User the running user cannot see, or a stale/missing User row. Do not word a
failure message as if it has proven one specific cause (for example “assigned to an inactive
user”) when the evaluator has only proven “no active, queryable User matched.”
IsActive = true is necessary but not sufficient for “healthy owner” in many orgs: Experience
Cloud/partner users, integration/automated-process users, and bot or test accounts left active in
production can all satisfy a naive active-User check while not being a real internal owner able to
do follow-up work. If that distinction matters, filter further on UserType, Profile, or a
dedicated approved-user or excluded-user criteria in the QUERY or an Apex Check.
When an optional relationship is used in message text, provide a fallback, for example
{!record.Parent.Name fallback="no parent account"}.
Outcomes and Reason Codes
Section titled “Outcomes and Reason Codes”| Outcome | When it occurs | What to investigate |
|---|---|---|
PASS | Pass Condition resolves to true | No action required |
FAIL | Pass Condition resolves to false | Review Found, Expected, and the configured failure guidance |
SKIPPED | Applicability or a prerequisite prevents evaluation | Review Applies To and Prerequisite Check |
UNABLE_TO_EVALUATE | Formula configuration, access, missing relationship data, or a null/invalid result prevents a conclusion | Review the stable Reason Code and authorized diagnostics |
ERROR | An unexpected Apex or Salesforce problem occurs | Review authorized diagnostics and Apex debug logs |
A null or non-Boolean Pass Condition result does not become FAIL; Record Health Check returns
UNABLE_TO_EVALUATE because it cannot make the configured decision reliably.
Access and transaction limits
Section titled “Access and transaction limits”- Evaluation uses the running user’s object, record, and field access.
- Use display formulas only for values the viewer is allowed to see.
- Parent traversal depends on the relationship and referenced fields being available to the user.
- Salesforce allows 100 Formula Evaluation calls in one Apex transaction. Record Health Check stops at 95 so it can return a controlled result before reaching that hard limit.
- Each applicable formula is evaluated for each record. For example, a Pass Condition plus Found, Expected, and applicability formulas can require four calls per record. At 25 records, that would require 100 calls, so the request is rejected before evaluation. Use a smaller Batch size or fewer formulas in one Check Set.
- A display formula can require extra attempts while its result type is detected. In Query Checks, an Expected Value or Value-to-find formula can also require extra attempts when Formula Result Type is Automatic.
- Saved-field and completed-text limits are documented in Field limits.
Additional Check configuration
Section titled “Additional Check configuration”The same Check can configure titles, category, severity, messages, applicability, prerequisites, action links, display behavior, and Platform Event publication. Those fields apply consistently across Evaluation Types; use the Check field reference rather than copying their definitions into each check-type reference.
Test coverage
Section titled “Test coverage”Test at least:
- A record that returns
PASS. - A record that returns
FAIL. - Blank values used by the formula.
- A missing parent relationship used by the formula.
- The intended user without access to one referenced field.
- Each applicability or prerequisite path configured on the Check.
Compatibility and deprecation
Section titled “Compatibility and deprecation”The Apex response does not contain a Formula-specific version number. Its global Apex types are the
compile-time contract supplied by the installed package. Flow responses currently report contract
2.0, and Platform Events report their separate contract 1.0. Removing or renaming a public
field, Status, or Reason Code requires a new contract version. No Formula field is currently
deprecated.
Related
Section titled “Related”Verify malformed-literal diagnostics in a sandbox
Section titled “Verify malformed-literal diagnostics in a sandbox”After deploying the integration fixtures, open an Account with Record Health Check and select
RHC_Diagnostic_Bad_Formula. The RHC_Diag_Formula_Open_Quote Check contains a lone opening quote;
RHC_Diag_Formula_Escaped_End ends with an escaped quote. Both must report UNABLE_TO_EVALUATE
with INVALID_FORMULA, a Diagnostic ID, and a corrective action. Neither is a business FAIL.
Their planner finding is INVALID_FORMULA_LITERAL, with [redacted literal] instead of literal
contents. The existing missing-formula, unclosed-function and missing-field fixtures remain in this
Set and retain their own expected diagnoses.
For recovery, clone either Check into a temporary sandbox Check Set. Replace its Pass Condition
with Name = "RHC Literal Healthy": the named Account should PASS, and an Account with a different
name should FAIL. Remove the temporary clone after verification; keep the diagnostic fixtures
malformed so future regression runs still test the failure path.
RHCDiagnosticBadConfigurationTest.savedUnterminatedLiteralsHaveRedactedLexicalFindings verifies
both saved formulas and redaction. Its two individual diagnostic tests verify the public evaluation
results. RHCDiagnosticAgentMcpSurfaceTest.formulaChecksReachAgentforceAndMcpWithDiagnosis covers
the native actions and REST adapter; RHCFormulaTokenizerGrammarTest covers empty, escaped and
unterminated string boundaries. These tests do not substitute for the sandbox card verification.