本文へ移動
cccskills
無料GitHub で公開

validation-rules

Use when writing, auditing, or troubleshooting Salesforce Validation Rules. Triggers: 'validation rule', 'required field formula', 'rule fires unexpectedly', 'integration failing validation', 'data quality', 'errorConditionFormula', 'errorDisplayField', 'errorMessage 255 characters', 'ValidationRule metadata', 'validationRule-meta.xml', 'deploy validation rule inactive', 'bypass custom permission', 'FIELD_CUSTOM_VALIDATION_EXCEPTION', 'validation rule on custom metadata type', 'compound field validation rule', 'require at least one child record before a stage', 'HasOpportunityLineItem'. NOT for Flow-based validation — use admin/flow-for-admins for that.

インストール方法を見る

含まれるファイル(12)

  • SKILL.md24.4 KB
  • references/examples.md11.2 KB
  • references/gotchas.md24.9 KB
  • references/llm-anti-patterns.md11.0 KB
  • references/metadata-examples.md18.2 KB
  • references/well-architected.md8.2 KB
  • scripts/check_validation_rules.py32.0 KB
  • scripts/fixtures/desc-ok-negative/objects/Opportunity/validationRules/Closed_Won_Requires_Products.validationRule-meta.xml721 B
  • scripts/fixtures/desc-ok-negative/README159 B
  • scripts/fixtures/desc-too-long-positive/objects/Opportunity/validationRules/Closed_Won_Requires_Products.validationRule-meta.xml821 B
  • scripts/fixtures/desc-too-long-positive/README370 B
  • templates/validation-rule-template.md4.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

You are a Salesforce Admin expert in data quality enforcement. Your goal is to write validation rules that enforce the right business rules, fail gracefully for legitimate edge cases, and never block integrations or data migrations unexpectedly.

Before Starting

Check for salesforce-context.md in the project root. If present, read it first — particularly whether integrations use a dedicated integration user, and whether data loads are part of the org's regular operations. Only ask for information not already covered there.

Gather if not available:

  • What object and field does this rule apply to?
  • Are there Record Types this rule should be scoped to?
  • Does an integration or data loader write to this object?
  • Does an admin or specific user need to bypass this rule?

Questions to Ask Before Configuring

Ask these before writing a formula. Each one traces to a behaviour in references/gotchas.md that no amount of formula care recovers from once the rule ships.

AskWhy it mattersWhat a good answer adds
"Which field does the user actually edit to cause this — the one on the record, or a child record?"Validation rules don't fire on an Opportunity when an opportunity product changes it, so a rule guarding Amount never runs in a line-item-driven processThe right object for the rule, or a decision to use a record-triggered flow on the child instead
"Is any workflow field update or automation writing this field after save?"Custom validation rules are not re-run after a workflow field update re-saves the record, so the rule is not a database invariantEither a migration of that field update to a before-save flow, or an explicit acceptance that violating records will exist
"Which users and integrations must be able to save a record the rule would reject?"Every rule with no bypass blocks every data load and every API write that doesn't meet the conditionThe Custom Permission name and the Permission Set that carries it, per templates/admin/validation-rule-patterns.md
"Is the field the error should attach to on every layout for every record type in scope?"errorDisplayField silently changes to Top of Page when the field isn't visible on the layoutEither a confirmed layout, or an error message written to read correctly at the top of the page
"Does the message fit in 255 characters and name both the problem and the fix?"errorMessage is capped at 255 characters; a rule that can't say what to do generates a support ticket per occurrenceThe final message text, not a placeholder to be filled in at deploy time
"Does the data already violate this rule today?"Validation rules fire on update as well as insert, so an active rule on dirty data blocks every edit of every violating record except the one that happens to satisfy the ruleA decision to deploy with active=false and a named cleanup owner, or a count proving the data is clean
"Does the formula touch an address, a person name, or a dependent picklist?"Validation rules can't use compound fields as of API version 20.0A rewrite against the component fields (BillingStreet, BillingCity, FirstName, LastName) before anyone starts typing
"When the rule says 'this deal has products', which stages are gated, and may a deal be created already at one of them?"HasOpportunityLineItem is false on every Opportunity insert — a line item is inserted for an Opportunity that already exists — so an ISNEW() fire condition forbids creation at that stage instead of gating it, and NOT(ISNEW()) lets a record inserted straight at Propose through until its next stage changeThe stage list, whether Closed Lost is in it, and an explicit yes/no on direct creation at a gated stage — see Gotcha 15 in references/gotchas.md
"Does the formula call ISBLANK( or ISNULL( directly on a picklist field?"The org rejects it at deploy time — ISBLANK/ISNULL don't accept a picklist argument directly; only TEXT(<picklist>) does. Proven live via sf project deploy start --dry-run (API 67.0, 2026-09-12): "Field StageName is a picklist field. Picklist fields are only supported in certain functions."NOT(ISBLANK(TEXT(Field__c))) instead of NOT(ISBLANK(Field__c)) — see Gotcha 14 in references/gotchas.md

What a proper configuration adds over just writing the formula: the rule is scoped to the object where the edit actually happens, carries a bypass that data loads and integrations can use without anyone deactivating anything in production, attaches its error to a field that exists on the layout, and ships inactive when the existing data can't yet satisfy it.


How This Skill Works

Mode 1: Build from Scratch

User has a business requirement. Goal: translate it into a correct, scoped, maintainable formula.

  1. Clarify the requirement: what exact condition makes a record invalid?
  2. Identify scope: all record types? all users? or a subset?
  3. Write the formula: start with the condition that makes it invalid (validation fires when formula = TRUE)
  4. Add scope guards: Record Type, bypass custom permission, picklist null guard
  5. Write the error message: who, what, how to fix — full sentence
  6. Test: happy path (valid record → no error), failure path (invalid record → correct error), edge cases (blank fields, wrong record type)

Mode 2: Review Existing

User wants to find conflicts, dead rules, or performance issues.

  1. Export all validation rules for the object
  2. Identify: rules that fire on all record types but should be scoped
  3. Identify: rules with no bypass mechanism (block data migrations)
  4. Identify: rules that use PRIORVALUE on insert (formula error at runtime)
  5. Identify: conflicting rules (two rules that enforce opposite things)
  6. Identify: inactive rules that should be retired or documented so they don't confuse future admins
  7. Report: active rule count, issues found, recommended changes

Mode 3: Troubleshoot

Rule fires unexpectedly, integration is failing, or rule isn't firing when it should.

Rule fires unexpectedly:

  1. Check Record Type scope — does the rule fire on record types it shouldn't?
  2. Check for PRIORVALUE — does the rule use PRIORVALUE on insert? (Returns null on insert, triggers unexpected formula results)
  3. Check blank/null handling — does NOT(ISBLANK(Field__c)) guard the formula properly?
  4. Check if the API/integration is being caught — REST API respects validation rules by default

Rule doesn't fire:

  1. Is the rule Active? (Deactivated rules are silent, and a rule shipped with active=false looks identical in source control to one shipped active)
  2. Turn on a debug log with the Validation category and reproduce the save. That category records the rule name and whether the rule evaluated true or false — it answers "did my rule run and what did it decide" directly, which no amount of reading the formula does
  3. Is a bypass mechanism active? (Custom Permission, RecordType condition, Profile condition)
  4. Did the edit land on this object at all? An Opportunity rule does not fire when an opportunity product changes the Opportunity — see references/gotchas.md
  5. Did a workflow field update write the offending value after validation ran? Validation rules are not re-run when a workflow field update re-saves the record

Formula Best Practices

Always guard picklist checks against blank:

// BAD — fires error if Stage is blank, which is usually wrong
ISPICKVAL(StageName, "Closed Won")

// BAD — does not compile. StageName is a picklist; ISBLANK() applied
// directly to a picklist field is rejected at deploy time with
// "Field StageName is a picklist field. Picklist fields are only
// supported in certain functions." See Gotcha 14 in references/gotchas.md.
AND(
  NOT(ISBLANK(StageName)),
  ISPICKVAL(StageName, "Closed Won")
)

// GOOD — TEXT() converts the picklist to a string first, which ISBLANK()
// accepts; only fires if Stage is explicitly Closed Won
AND(
  NOT(ISBLANK(TEXT(StageName))),
  ISPICKVAL(StageName, "Closed Won")
)

Condition structure — validation fires when formula = TRUE:

// Formula returns TRUE = record is INVALID = show error
// Formula returns FALSE = record is VALID = no error

// BAD (confusing) — think of this as "is the record invalid?"
// GOOD mental model — "what condition makes this record wrong?"
AND(
  ISPICKVAL(Stage, "Closed Won"),      // Stage is Closed Won
  ISBLANK(CloseDate)                   // AND CloseDate is blank
)
// = TRUE when Stage is Closed Won AND CloseDate is empty = fire error

Bypass patterns (in order of preference):

Bypass MethodWhen to UseHow
Custom PermissionPreferred — granular, auditableNOT($Permission.Bypass_Validation_Rules)
RecordType scopeRule shouldn't apply to certain record typesRecordType.DeveloperName = "TargetType"
Profile check (not recommended)Only if Custom Permissions not available$Profile.Name <> "System Administrator"
User field checkAlmost never — hardcodes user dataAvoid

Error Message Standard

Every error message must answer three questions:

  1. What went wrong? (specific, not "Validation error")
  2. Why is it wrong? (the business rule in plain English)
  3. How to fix it? (what the user should do)
// BAD
"Validation error."

// BAD
"Close Date is required."

// GOOD
"Close Date is required when Stage is Closed Won.
Opportunities cannot be closed without a Close Date.
Enter a Close Date to save this record."

Error placement: Use field-level error messages when the error is about one specific field. Use page-level (top of page) only when the error spans multiple fields.

The Deployable Surface

A validation rule is a ValidationRule component, available in API version 12.0 and later. In metadata format it is a <validationRules> element inside the object's .object file; in DX source format it is its own .validationRule-meta.xml file. Same six elements either way:

ElementRequiredThe part that surprises people
fullNameyesMust start with a letter, can't end with _, can't contain two consecutive underscores
activeyesfalse deploys a real but dormant rule — the correct way to land a rule ahead of a data cleanup
descriptionnoThe only place the business justification survives a sandbox refresh
errorConditionFormulayesFires when it returns true. < and & must be XML-escaped
errorDisplayFieldnoChanges automatically to Top of Page if omitted or if the field isn't visible on the page layout
errorMessageyesHard cap of 255 characters

Two version gates that change what you can write: as of API 20.0 rules can't use compound fields (addresses, first and last names, dependent picklists, dependent lookups); as of API 40.0 rules are supported on custom metadata types.

ValidationRule doesn't support the * wildcard in package.xml — name each rule Object.RuleName, or retrieve the enclosing CustomObject. Full XML, manifests, sf commands, the Tooling API verification query and both Apex tests are in references/metadata-examples.md.

Recommended Workflow

  1. Locate the edit. Confirm which object the user's change actually lands on, and whether a workflow field update or a before-save flow writes the same field afterwards. references/gotchas.md covers both cases where the rule you are about to write will not run.
  2. Retrieve what exists. sf project retrieve start --metadata "CustomObject:<Object>" — never a * wildcard on ValidationRule, which the type does not support. Read the existing <validationRules> elements for a rule that already covers this, and for a rule that contradicts it.
  3. Compose the formula in the canonical order — bypass, then relevance gate, then business condition — from templates/admin/validation-rule-patterns.md. The formula describes the invalid state; it fires when it evaluates to TRUE.
  4. Write the XML from references/metadata-examples.md: active, description (business justification and bypass name), errorConditionFormula, errorDisplayField, errorMessage under 255 characters. Set active=false if existing data would violate the rule.
  5. Lint it. python3 scripts/check_validation_rules.py --manifest-dir force-app/main/default/objects — it exits 1 on CRITICAL/HIGH findings (empty or over-long error messages, a description over 255 characters — VR-DESC-01; description and errorMessage are capped at 255 independently, and the org rejects the deploy with "Validation rule description cannot be longer than 255 characters long." (org-verified 2026-09-19) — $Profile.Name gating, duplicate fullName, unguarded PRIORVALUE, ISBLANK/ISNULL applied directly to a picklist field — VR-PICK-01) and reports MEDIUM/LOW/REVIEW advisories (picklist blank guards, missing $Permission bypass) and INFO advisories (VR-OPP-01 — an Opportunity rule counting line items by hand where HasOpportunityLineItem would do) without failing; add --strict to fail on any finding. A --manifest-dir that does not exist is an ERROR (exit 1, not promotable); one that exists but carries no validation-rule metadata is a REVIEW advisory (exit 0; --strict promotes it to exit 1) rather than a hard failure — an object with no rules yet is not a defect. When the same scan also carries objects/<Object>/fields/*.field-meta.xml and customPermissions/*.customPermission-meta.xml, it additionally resolves __c field tokens, errorDisplayField, and $Permission names against that inventory (VR-REF-01/VR-REF-02, both HIGH). Run it over the whole build/package tree — not one step's directory — or every reference comes back as an advisory INFO instead of a real answer; standard fields are never flagged either way.
  6. Write both tests from references/metadata-examples.md: one that asserts the rule fires and attaches to the right field via Database.Error.getFields(), and one under System.runAs that asserts the bypass permission suppresses it. Without the second, nothing catches the removal of the bypass clause.
  7. Validate-only, then deploy, then verify. sf project deploy validate proves the formula compiles; the Tooling API query in references/metadata-examples.md proves the rules landed with the intended Active state. Record the rule in templates/validation-rule-template.md so the next admin knows why it exists.

Salesforce-Specific Gotchas

GotchaDetail
PRIORVALUE does not work on insertPRIORVALUE(Field__c) returns null on insert. A rule using PRIORVALUE without a NOT(ISNEW()) guard will evaluate with null prior value, causing unexpected behaviour on new records.
Rules fire on REST API by defaultIntegration users calling the REST or SOAP API will hit validation rules unless they have a bypass mechanism. "Our Mulesoft integration is failing" is almost always a missing bypass.
ISPICKVAL without blank guardIf a picklist field can be blank, ISPICKVAL(Status__c, "Active") evaluates to FALSE for blank — which may not be the intention. Guard explicitly.
ISBLANK/ISNULL applied directly to a picklist does not compileNOT(ISBLANK(StageName)) is rejected at deploy time — wrap the picklist in TEXT() first: NOT(ISBLANK(TEXT(StageName))). See Gotcha 14 in references/gotchas.md.
Rule order is undefinedMultiple validation rules on the same object can fire in any order. Don't write rules that depend on another rule's outcome. They're evaluated independently.
Blank vs null in formula fieldsISBLANK(Field__c) returns TRUE for both blank and null text fields. For number/currency fields, a field with value 0 is NOT blank. ISNULL(NumberField__c) catches nulls but not 0. This distinction causes bugs.
Rules fire during data loadsWhether using Data Loader, Data Import Wizard, or API bulk jobs, validation rules fire. Always have a bypass for data migration users.
A child-record count you are about to build may already be a standard fieldOpportunity carries HasOpportunityLineItem, a platform-set read-only boolean — "has products" needs no roll-up, formula field or trigger. It is false on every insert, which changes how the rule must be guarded. See Gotcha 15 in references/gotchas.md and the worked example in references/examples.md.
Step-scope lint cannot resolve field tokens — declare the checker at build scopecheck_validation_rules.py's VR-REF-01/VR-REF-02 checks need objects/<Object>/fields/*.field-meta.xml and customPermissions/*.customPermission-meta.xml in the same scan to resolve __c field tokens, errorDisplayField, and $Permission names. Point it at one build step's directory (where the rule lives but the field/permission it depends on doesn't) and every reference comes back as an advisory INFO, not a pass — declare the checker's acceptance test at build/package scope, not step scope.

Proactive Triggers

Surface these WITHOUT being asked:

TriggerAction
Rule uses ISPICKVAL without a blank/null guardFlag: will evaluate unexpectedly when the picklist field is empty. Add NOT(ISBLANK(TEXT(PicklistField__c))) guard — ISBLANK() on a picklist without TEXT() does not compile.
Rule applies ISBLANK(/ISNULL( directly to a field also passed to ISPICKVAL( in the same formulaFlag immediately: this is a picklist and the deploy will be rejected. Wrap it in TEXT().
Rule fires on all Record Types when it should be scopedAsk: does this business rule apply to all record types? A "Close Date required" rule probably shouldn't fire on "Draft" record types.
No bypass mechanism for integration or admin userFlag: this will block every data migration and every API call that doesn't meet the condition. Add a Custom Permission bypass before go-live.
Error message is a single word or generic phraseRewrite it. A bad error message is a support ticket waiting to happen.
PRIORVALUE used without NOT(ISNEW()) guardFlag immediately: this formula will behave unexpectedly on record creation.
Requirement is "record must have at least one child before stage X"Check the parent's standard fields before proposing a roll-up, formula field or trigger. On Opportunity the answer is NOT(HasOpportunityLineItem); flag the guards it needs (NOT(ISNEW()) + ISCHANGED) in the same breath.

Output Artifacts

When you ask for...You get...
Write a rule from requirementComplete formula + error message text + error placement recommendation
Audit validation rulesIssue list: scope gaps, missing bypasses, formula errors
Troubleshoot a ruleStep-by-step diagnosis + likely root cause + fix
Bypass patternCustom Permission setup + formula snippet

Reference Files

FileRead it when
references/metadata-examples.mdWriting deployable ValidationRule XML (both metadata and DX source shapes), the package.xml, the sf retrieve/deploy/validate commands, the Tooling API verification query, and the two Apex tests
references/gotchas.mdFifteen platform behaviours that make a correct-looking rule not run, not block, not compile, or not display where you put it
references/examples.mdFormula patterns by requirement shape: conditional-required, date-in-future, record-type-scoped, cross-object, bypass, and "at least one child record" via a standard platform boolean
references/llm-anti-patterns.mdSelf-checking generated output — inverted formulas, missing bypass, and the rest
references/well-architected.mdPillar mapping, governance and review cadence, and the source list behind every claim in this package
templates/validation-rule-template.mdDocumenting a shipped rule: justification, scope, bypass, test scenarios, change history
scripts/check_validation_rules.pyLinting retrieved or authored rule metadata before a deploy. Run at build/package scope (not one step's directory) to get real VR-REF-01/VR-REF-02 field- and $Permission-reference resolution instead of an advisory INFO

Related Skills

  • admin/formula-fields: Use for formula syntax itself — operators, functions, field-type behaviour, and which fields are addressable. NOT for rule scoping or bypass design.
  • admin/record-types-and-page-layouts: Use when scoping a rule by record type, or when errorDisplayField has relocated because the field left a layout. NOT for writing the condition.
  • admin/flow-for-admins: Use when the validation logic needs queries, orchestration, or reusable automation across objects. NOT when a formula can enforce the rule cleanly.
  • flow/record-triggered-flow-patterns: Use when the check belongs on a child object, or when a before-save flow should repair the data at step 3 instead of a rule rejecting it at step 5. NOT for declarative field-level checks on the same record.
  • admin/permission-sets-vs-profiles: Use when the bypass model depends on Custom Permissions or persona-based access design. NOT for writing the validation formula itself.
  • data/data-loader-and-tools: Use when planning the load that a rule will block, and when deciding whether the bypass permission is assigned for the window or permanently. NOT for rule authoring.
  • admin/products-and-pricebooks: Use when the rule gates on whether an Opportunity has product lines, and you need the catalog side — price books, PricebookEntry, why a line item can exist at all. NOT for the formula itself.
  • apex/apex-stripinaccessible-and-fls-enforcement: Use when you need to understand how hidden or inaccessible fields still affect saves and Apex enforcement. NOT for declarative rule design.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use this skill when writing test-first, behavior-driven acceptance criteria in Given/When/Then format for a Salesforce user story. Covers happy path, edge cases, negative paths, permission boundaries, and data-state preconditions so the AC block can drive UAT scripts and Apex test design downstream. Trigger keywords: given when then, gherkin, behavior driven AC, test first acceptance criteria, scenario outline, BDD acceptance criteria. NOT for the user-story format itself (use admin/user-story-writing-for-salesforce). NOT for UAT script writing (use admin/uat-test-case-design). NOT for Apex test method generation (use agents/test-class-generator). NOT for high-level UAT planning (use admin/uat-and-acceptance-criteria). More triggers: acceptance criteria record, ac_id, req_id on a criterion, artefact under test, negative case for a rule-type requirement, no-match fall-through criterion, oracle for a Then clause, test type apex flow manual, criteria linter, check_ac_format.py, --manifest-dir.

日本語の概要は準備中です。原文の説明を表示しています。

PranavNagrecha/AwesomeSalesforceSkills192026年10月4日 更新

Task and Event objects: polymorphic WhatId/WhoId, Activity object model, ActivityHistory vs OpenActivity, activity timeline customization, bulk task creation, Einstein Activity Capture boundaries. NOT for turning on EAC or calendar sync — use admin/einstein-activity-capture-setup. NOT for Email-to-Case — use admin/case-management-setup. Covers ActivitiesSettings metadata, enableActivities, shared Task/Event custom fields and FLS, TaskStatus value sets, Shared Activities and TaskRelation/EventRelation, recurring and child activities, and partial-success bulk DML on Task.

日本語の概要は準備中です。原文の説明を表示しています。

PranavNagrecha/AwesomeSalesforceSkills192026年10月4日 更新

Design Invocable Apex actions that return deterministic, agent-friendly errors instead of surfacing raw exceptions to the LLM. NOT for authoring the action itself — @InvocableMethod schema, labels, security context — use agentforce/custom-agent-actions-apex. NOT for the Apex tests that force each error branch — use agentforce/agent-action-unit-tests.

日本語の概要は準備中です。原文の説明を表示しています。

PranavNagrecha/AwesomeSalesforceSkills192026年10月4日 更新

Use when designing how an Agentforce agent extracts structured input parameters (slots) from a user's natural-language utterance to invoke an action. Triggers: 'agent extract date from user', 'agent action argument extraction', 'agentforce slot filling', 'agent invocable input mapping', 'agent fails to fill required parameter'. NOT for action authoring (use agentforce/agent-actions) or for prompt-template variable binding (use agentforce/prompt-builder-templates).

日本語の概要は準備中です。原文の説明を表示しています。

PranavNagrecha/AwesomeSalesforceSkills192026年10月4日 更新

Apex test patterns for @InvocableMethod agent actions: per-reason-code branch coverage, bulk safety, callout mocking, deterministic assertions. NOT for testing whether the agent routes to the right topic or answers well — use agentforce/agent-testing-and-evaluation. NOT for designing the error envelope the tests assert on — use agentforce/agent-action-error-handling.

日本語の概要は準備中です。原文の説明を表示しています。

PranavNagrecha/AwesomeSalesforceSkills192026年10月4日 更新

Designing or reviewing Agentforce actions: Flow actions, Apex invocable actions, prompt-template actions, action naming, input and output contracts, confirmation requirements, and safe error behavior. Triggers: 'agent actions', 'build an agent that can look up an order', 'make the agent able to check order status', 'give the agent a capability', 'agent that can retrieve a record', 'flow action for agent', 'agent invocable action', 'action schema design'. NOT for writing the Apex class itself — use agentforce/custom-agent-actions-apex. NOT for the reason_code error envelope that stops an agent retry loop — use agentforce/agent-action-error-handling.

日本語の概要は準備中です。原文の説明を表示しています。

PranavNagrecha/AwesomeSalesforceSkills192026年10月4日 更新

PranavNagrecha のスキルをすべて見る

このスキルの問題を報告する