Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All articles
Admin·May 15, 2026·12 min read·62 views

Salesforce Validation Rules: 20 Real-World Examples Every Admin Should Know

Anatomy of a rule, ISCHANGED/ISNEW/PRIORVALUE/REGEX patterns, 20 working examples, error message best practices, and the gotchas that get missed.

Salesforce Validation Rules: 20 real-world examples every admin should know
By Dipojjal Chakrabarti · Founder & Editor, Salesforce DictionaryLast updated May 6, 2026

A sales rep tries to close an Opportunity and gets the error "Invalid input." That is the entire message. They open a ticket, you investigate, and the cause is a validation rule that requires the Loss Reason field when StageName is Closed Lost. The error message was written by someone who never sat next to a rep at end of quarter, and now you have a support ticket that did not need to exist. This guide is how to build validation rules that prevent the original bad save and prevent the support ticket that follows it.

Validation rules are the most underrated tool in the admin toolbox. They cost nothing to build, run instantly, and prevent more bad data than any downstream cleanup script. This article is the canonical 2026 reference. Anatomy, patterns, and 20 working examples you can paste into your org tonight, plus the message-writing habits that determine whether a rule helps or annoys.

Anatomy of a validation rule

A validation rule is two things:

  1. An error condition formula that returns TRUE or FALSE. When TRUE, the save blocks.
  2. An error message that the user sees.
Rule Name:        Email_Required_For_Customer
Error Condition:  AND(
                    ISPICKVAL(Type, 'Customer'),
                    ISBLANK(Email)
                  )
Error Message:    Email is required for Customers.
Error Location:   Field "Email"

The error formula is true, save blocks, user sees the message. The "error location" controls where the message appears (next to a specific field, or at the top of the page). Always pick the specific field when the rule is about one field; the inline location is the difference between a user who fixes the issue in five seconds and one who scrolls to the top, reads the message, and has to look for the relevant field on their own.

Anatomy of a validation rule: formula, message, location

The four core functions

Internalize these and you will write 90 percent of validation rules without looking anything up.

FunctionUse when
ISCHANGED(field)The field changed in this save (insert: always TRUE; update: depends)
ISNEW()The record is being inserted (not updated)
PRIORVALUE(field)The value of field before this save (only useful with ISCHANGED)
REGEX(text, pattern)Text matches a regex pattern. Best for format validation

Combined examples:

// Block changes to Stage from "Closed Won" back to anything else
AND(
  ISCHANGED(StageName),
  PRIORVALUE(StageName) = 'Closed Won'
)

// Require Email format on creation only (not edits)
AND(
  ISNEW(),
  NOT(REGEX(Email, '^[A-Za-z0-9._-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$'))
)

A common mental model: ISNEW() answers "is this an insert?", ISCHANGED() answers "did the field move this transaction?", PRIORVALUE() answers "what was it before?", and REGEX() answers "does the text fit the pattern?" Most production validation rules are a Boolean combination of these four with some literal field comparisons mixed in.

20 real-world examples

Each is a formula you can paste directly. Adjust field API names to match your org.

Text format (Examples 1-4)

1. Email format validation

AND(
  NOT(ISBLANK(Email)),
  NOT(REGEX(Email, '^[A-Za-z0-9._-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$'))
)

Error: "Email must be in valid format (user@example.com)."

2. US phone number format

AND(
  NOT(ISBLANK(Phone)),
  NOT(REGEX(Phone, '^\\(?\\d{3}\\)?[\\s.-]?\\d{3}[\\s.-]?\\d{4}$'))
)

Error: "Phone must be in (555) 123-4567 format."

3. ZIP code validation (US)

AND(
  NOT(ISBLANK(MailingPostalCode)),
  NOT(REGEX(MailingPostalCode, '^\\d{5}(-\\d{4})?$'))
)

Error: "ZIP must be 5 digits or 5+4 (12345 or 12345-6789)."

4. No special characters in account name

NOT(REGEX(Name, '^[A-Za-z0-9\\s.,&\\-\']+$'))

Error: "Account Name can only contain letters, numbers, spaces, and standard punctuation."

Dates (Examples 5-8)

5. Close Date cannot be in the past on create

AND(
  ISNEW(),
  CloseDate < TODAY()
)

Error: "Close Date cannot be in the past."

6. Close Date must be at least 7 days from today on create

AND(
  ISNEW(),
  CloseDate < TODAY() + 7
)

Error: "Close Date must be at least 7 days out."

7. Birth date must be in the past

AND(
  NOT(ISBLANK(Birthdate)),
  Birthdate > TODAY()
)

Error: "Birth date cannot be in the future."

8. End Date must be after Start Date

AND(
  NOT(ISBLANK(End_Date__c)),
  NOT(ISBLANK(Start_Date__c)),
  End_Date__c < Start_Date__c
)

Error: "End Date must be on or after Start Date."

Money / amounts (Examples 9-11)

9. Discount cannot exceed 50 percent

AND(
  NOT(ISBLANK(Discount__c)),
  Discount__c > 0.5
)

Error: "Discount cannot exceed 50%."

10. Opportunity Amount required for Closed Won

AND(
  ISPICKVAL(StageName, 'Closed Won'),
  OR(ISBLANK(Amount), Amount <= 0)
)

Error: "Amount is required and must be positive when Stage is Closed Won."

11. Annual Revenue must be positive

AND(
  NOT(ISBLANK(AnnualRevenue)),
  AnnualRevenue < 0
)

Error: "Annual Revenue cannot be negative."

Status transitions (Examples 12-14)

12. Cannot move Stage backward from Closed Won

AND(
  ISCHANGED(StageName),
  TEXT(PRIORVALUE(StageName)) = 'Closed Won',
  TEXT(StageName) != 'Closed Won'
)

Error: "Once Stage is Closed Won, it cannot be moved back."

13. Closed Lost requires a reason

AND(
  ISPICKVAL(StageName, 'Closed Lost'),
  ISBLANK(TEXT(Loss_Reason__c))
)

Error: "Loss Reason is required when Stage is Closed Lost."

14. Case cannot be Closed without resolution notes

AND(
  ISPICKVAL(Status, 'Closed'),
  ISBLANK(Resolution_Notes__c)
)

Error: "Resolution Notes are required to close a Case."

Cross-object (Examples 15-17)

15. Opportunity Amount cannot exceed Account's annual revenue

AND(
  NOT(ISBLANK(Amount)),
  NOT(ISBLANK(Account.AnnualRevenue)),
  Amount > Account.AnnualRevenue
)

Error: "Opportunity Amount cannot exceed the Account's Annual Revenue."

16. Contact's email domain must match account's website

AND(
  NOT(ISBLANK(Email)),
  NOT(ISBLANK(Account.Website)),
  NOT(CONTAINS(Email,
    SUBSTITUTE(SUBSTITUTE(Account.Website, 'http://', ''), 'https://', '')))
)

Error: "Contact's Email domain should match the Account's Website."

17. Quote line item count limit per opportunity (workaround using rollup)

AND(
  NOT(ISBLANK(Opportunity.Total_Quote_Lines__c)),
  Opportunity.Total_Quote_Lines__c >= 50
)

Error: "Cannot add more than 50 quote line items per Opportunity."

Record-type specific (Examples 18-20)

18. SLA fields required for Premium Support cases only

AND(
  RecordType.DeveloperName = 'Premium_Support',
  OR(ISBLANK(TEXT(SLA_Tier__c)), ISBLANK(SLA_Response_Time__c))
)

Error: "SLA Tier and Response Time are required for Premium Support cases."

19. B2C accounts must have Person Account fields populated

AND(
  RecordType.DeveloperName = 'Person_Account',
  OR(ISBLANK(FirstName), ISBLANK(LastName))
)

Error: "First and Last Name are required for Person Accounts."

20. Internal cases cannot have customer-facing fields filled

AND(
  RecordType.DeveloperName = 'Internal_Issue',
  NOT(ISBLANK(Customer_Communication__c))
)

Error: "Customer-facing fields are not allowed on Internal Issues."

20 examples categorized by type

Error message best practices

The error message is half the rule. A bad message creates a support ticket; a good one teaches the user.

Bad: "Invalid input." Better: "Email cannot be blank." Best: "Email is required for Customers. Please add a valid email like jane@example.com."

The pattern: what is wrong, why, and how to fix.

Other guidelines:

  • Address the user, not the system. "You must fill in..." not "System requires..."
  • Suggest a fix, not just the rule. "Use format (555) 123-4567" beats "Phone must match regex."
  • Locate the message at the relevant field. Do not dump everything at the top of the page.
  • Localize. If your org is multi-language, build messages with $Label.X references where possible.
  • Do not expose sensitive logic. "Discount above 50 percent requires VP approval" is fine; "VP IDs are 005xxx" is a leak.
  • Match the tone of the surrounding UI. A casual product surface gets a casual error; a compliance-heavy product gets formal language. Pick one and use it consistently across rules so the experience is coherent.

The patterns that bite

A short list of validation-rule edge cases that catch new admins.

Pattern 1: ISCHANGED plus ISNEW behavior

ISCHANGED(field) returns TRUE on insert (the value "changed" from null). If you want to validate only on edits, combine: AND(NOT(ISNEW()), ISCHANGED(field)).

Pattern 2: PRIORVALUE in test classes

PRIORVALUE returns null in some tests. If your rule depends on it, build proper Apex test class coverage that performs an update operation, not just an insert. A common pitfall is asserting the rule fires during a setup-only test and concluding the rule works; the rule actually only catches the update path, and the assertion was meaningless.

Pattern 3: Picklist comparisons

Always wrap picklist values in ISPICKVAL() or TEXT(). Direct equality (StageName = 'Closed Won') sometimes works in formulas but can misbehave with multi-currency or translated values. Make the wrap a team convention so new admins copy the right pattern from existing rules.

Pattern 4: Cross-object null checks

A cross-object formula like Account.AnnualRevenue > 1000000 returns null (treated as false) when the parent is not set. Always include NOT(ISBLANK(Account.AnnualRevenue)) first.

Pattern 5: Mass transfer skips validation

Salesforce's "Mass Transfer Records" tool skips validation rules. So does the Apex Database.update(records, false) flavor with allOrNothing=false. So do most data loaders. If your validation rule must hold even for mass operations, also enforce in Apex or a record-triggered Flow. The pattern: a Validation Rule for the interactive UI, a Flow for bulk operations, and a before update trigger for anything that must hold without exception.

Pattern 6: Record-Triggered Flow can be a better fit

In 2026, complex validation often goes in a record-triggered Flow instead. Easier to debug, supports multi-step logic, can call Apex sub-flows. Reserve validation rules for simple field-level invariants.

The five gotchas, with the fix for each

When NOT to use a validation rule

  • Defaulting a field value. Use a formula field, page-layout default, or before-save Flow.
  • Calculating a field from other fields. Use a formula field or Apex.
  • Multi-step business logic. Use a Flow.
  • Workflow-style "if X then send Y" rules. Validation rules block. They do not side-effect.
  • Anything that needs to be skippable by some users. Use a permission-aware Flow that branches on user attributes.

The right validation rule is short, declarative, and "this combination is not allowed" in shape. Anything longer than roughly ten lines of formula is a smell, and the right response is to move the logic into a Flow or an Apex check that can be unit tested.

How Agentforce interacts with validation rules

When an agent calls an Apex Action that updates a record, validation rules fire. The agent's request fails if the rule blocks save, and the agent has to handle that error path, often by asking the user for clarification.

Two implications:

  1. Test agent flows with realistic data. Validation rules that fire only in edge cases will surface the first time an agent hits them in production. A scripted test against the agent that intentionally triggers each high-risk validation rule is the cheapest insurance you can buy.
  2. Error messages reach the agent. A clear "Email is required for Customers" message lets the agent ask the user politely. A vague "Invalid input" leaves the agent confused.

The second implication is why the message-quality discipline in this guide matters even more in 2026 than it did before. Your agent reads the same message a human would, and a vague message produces a vague agent response.

Common admin mistakes

  • Stacking 20 rules on one object. They run on every save. Combine where possible.
  • Long, complex formulas with no comments. Future-you will hate present-you. Add a top-of-formula comment that names the business rule in one sentence.
  • Vague error messages. "Invalid" tells nobody anything.
  • Forgetting that validation rules do not enforce on integrations by default. Add Apex-level enforcement for paths that bypass them.
  • Using LEFT(Phone, 3) = '555' instead of REGEX. REGEX is more readable and handles edge cases.
  • Not testing the rule in a sandbox before deploy. Validation rules ship as metadata, but the test happens in your head if you skip the sandbox. Always run a one-record happy-path save and a one-record failing-path save before promoting.

Frequently asked questions

Can a validation rule fire on a delete? No. Validation rules fire on insert and update only. Use a trigger for delete-blocking.

Can I disable a validation rule for a specific user? Yes. Add a check like NOT($Permission.Bypass_Validation__c) and grant the custom permission to specific users via Permission Sets.

Do validation rules slow down saves? Negligibly. They are evaluated as formulas. The only time they bite is if you have hundreds firing on bulk DML, where each evaluation adds CPU.

Can validation rules call Apex? No. Validation rules are formula-only. For logic that needs Apex, use a record-triggered Flow with an invocable Apex method, or write the logic directly in a Trigger.

How do I see which validation rules fired? Salesforce returns the failure as part of the save error. The standard UI shows the message; in the API, the response includes the rule name. For tracing, enable debug logs on the running user.

How do I version validation rules across orgs? Validation rules deploy as metadata. Treat them like code. Pull them into source, review changes in PRs, and ship them through your pipeline. Click-driven validation rule edits in production are exactly the kind of thing that surprises the next admin during a release.

If you only adopt one habit, write the error message first. Decide what the user needs to know. Then build the formula that triggers it. The rule that comes out of that order is always better than the one that starts with the formula, because the message is the only part of the rule the user ever sees and the formula exists to serve it.

A practical follow-up habit: keep a one-page document that lists every validation rule in the org, the business reason it exists, and the team that owns it. Update it whenever you add a rule. A year from now, when somebody asks "why does this save fail?", the answer is in the doc rather than in a debug log. Senior admins call this kind of artifact a rule register, and the orgs that maintain one have noticeably fewer "why is this broken?" tickets per quarter.

About the Author

Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.

Share this article

Share on XLinkedIn

Sources

Related dictionary terms

Comments

    No comments yet. Start the conversation.

    Sign in to join the discussion. Your account works across every page.

    Keep reading