Skip to content

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.

Setup fieldAPI nameRequirement
Evaluation TypeEvaluationType__cVerify with a formula: FORMULA
Pass ConditionPassConditionFormula__cRequired Boolean formula; true returns PASS, false returns FAIL
Display: Found FormulaDisplayFoundFormula__cOptional display-only Found value
Display: Expected FormulaDisplayExpectedFormula__cOptional display-only Expected value
Formula Result TypeFormulaResultType__cKeep 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.

  • 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 AnnualRevenue or Custom_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 example Owner: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 Name pseudo-entity. For example, What:Account.Name is supported, while an Account-only field such as What:Account.Industry requires 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, and Owner.LastName. For polymorphic owners that require an explicit type, use Owner:User.Field; a path that does not match the object’s schema can return FIELD_NOT_RESOLVED.
  • $User, $Profile, $Setup, $Permission, and other global merge references are never treated as record fields; a formula that reads $User.Id never adds a bogus User.Id path to the record query. FormulaEval rejects these globals in record context, and Record Health Check returns UNABLE_TO_EVALUATE with INVALID_FORMULA rather 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).

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.

PatternExampleQueue/Group ownerMissing/inaccessible User
Formula Owner:User.IsActiveCustom Formula CheckUNABLE_TO_EVALUATE. FormulaEval cannot resolve a User-only path against a non-User owner, and a null formula result never becomes FAILUNABLE_TO_EVALUATE, for the same reason
QUERY SELECT COUNT() FROM User WHERE Id = {!record.OwnerId} AND IsActive = trueAccount_EU_OwnerIsActiveFAIL. A Queue/Group Id never matches a User row, so the count is 0FAIL. 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"}.

OutcomeWhen it occursWhat to investigate
PASSPass Condition resolves to trueNo action required
FAILPass Condition resolves to falseReview Found, Expected, and the configured failure guidance
SKIPPEDApplicability or a prerequisite prevents evaluationReview Applies To and Prerequisite Check
UNABLE_TO_EVALUATEFormula configuration, access, missing relationship data, or a null/invalid result prevents a conclusionReview the stable Reason Code and authorized diagnostics
ERRORAn unexpected Apex or Salesforce problem occursReview 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.

  • 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.

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 at least:

  1. A record that returns PASS.
  2. A record that returns FAIL.
  3. Blank values used by the formula.
  4. A missing parent relationship used by the formula.
  5. The intended user without access to one referenced field.
  6. Each applicability or prerequisite path configured on the Check.

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.

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.