home Homebuild Toolsbug_report Errorsmenu_book Guideslightbulb Tipssmart_toy Promptsextension Extensionsfolder_open Resourcesinfo About
search
error

System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Revenue must be greater than zero: [AnnualRevenue]

What does this error mean?

Salesforce validation rules evaluate field values on a record whenever a DML operation (insert, update, upsert) is attempted. If the rule's error condition formula evaluates to true, Salesforce blocks the DML and throws this exception. The error message and field name in brackets both come directly from the validation rule configuration.

This error appears in both the UI (as a page-level message) and in Apex (as a System.DmlException with status code FIELD_CUSTOM_VALIDATION_EXCEPTION). In Apex, the getFields() method on the error object returns the API name of the field the rule is attached to.

Anatomy of the exception message

Status Code FIELD_CUSTOM_VALIDATION_EXCEPTION
Error Message <Your validation rule's Error Message>
Field [AnnualRevenue] — API name of field the rule targets
Row Index First exception on row 0 — first failing record in the list
warning

Not always a bug: This error is often correct behaviour — a validation rule is doing exactly what it was designed to do. The fix may be updating your Apex code to set the right field values, not removing the validation rule.

Common Causes

1. Apex Code Setting Incorrect Field Values

Automations, triggers, or integrations that create or update records programmatically often skip populating required fields that a validation rule checks. A rule that says "Phone is required when Status is Active" will block any Apex that sets Status to Active without also setting Phone.

2. Validation Rule Added After Existing Automation

A new validation rule is deployed to an org where existing Apex automations were never updated to account for it. The automation had previously set a field value that now violates the new rule.

3. Integration Payloads Missing Required Fields

An external system pushing records via the REST or SOAP API does not include all fields that validation rules require. The partial payload passes schema validation but fails business logic validation.

4. Test Data Not Matching Validation Criteria

Test classes that create minimal records (just enough to satisfy required fields) fail because a validation rule's criteria require additional fields to be populated with specific values.

5. allOrNone = true Rolling Back Valid Records

With the default allOrNone = true DML behaviour, a single record in a list failing validation causes the entire operation to roll back — including records that would have passed. This surfaces the error even when most records are perfectly valid.

How to Debug It

Before writing any fix, you need to identify exactly which validation rule is firing and which field value is the problem. Follow this sequence:

1

Read the full error message

The text in the exception is your validation rule's exact error message. Search for it in Setup → Validation Rules to find the culprit rule instantly.

2

Check the field name in brackets

The API field name inside [] tells you exactly which field the rule evaluates. That's the field your code likely has a wrong value on.

3

Log the failing record's field values

Use JSON.serializePretty(record) in a debug log to inspect every field value on the record right before the DML call.

4

Read the validation rule formula

Go to Setup → Object Manager → [Object] → Validation Rules → [Rule Name]. Read the Error Condition Formula to understand exactly what values will trigger it.

5

Compare record values against the formula

Manually evaluate the formula with your record's field values. If it evaluates to true, the rule fires. Adjust your Apex to produce values that make the formula false.

How to Fix It

Solution 1: Inspect and Fix the Record's Field Values

The most direct fix — make sure your Apex sets the field values the validation rule requires. Log the record before DML to see exactly what you're sending.

Apex — Debug Before DML
Account acc = new Account(
    Name      = 'Acme Corp',
    Status__c = 'Active'
    // ❌ Missing Phone — validation rule requires it when Active
);

// Log before DML to see exactly what you're inserting
System.debug(JSON.serializePretty(acc));

// ✅ Fix: populate the field the rule requires
acc.Phone = '415-555-0100';
insert acc;

Solution 2: Handle Validation Errors Gracefully with Partial DML

Use Database.insert(allOrNone:false) to process valid records and collect failures separately, so one bad record doesn't block the whole batch. Log or surface validation errors clearly for each failing record.

Apex — Partial DML with Error Handling
List<Database.SaveResult> results =
    Database.insert(accountList, false); // allOrNone = false

List<String> errors = new List<String>();

for (Integer i = 0; i < results.size(); i++) {
    if (!results[i].isSuccess()) {
        for (Database.Error err : results[i].getErrors()) {

            // Detect validation rule failures specifically
            if (err.getStatusCode() ==
                StatusCode.FIELD_CUSTOM_VALIDATION_EXCEPTION) {

                errors.add(
                    'Row ' + i + ': Validation failed — '
                    + err.getMessage()
                    + ' Field(s): ' + err.getFields()
                );
            }
        }
    }
}

if (!errors.isEmpty()) {
    System.debug(LoggingLevel.WARN,
        'Validation errors:\n' + String.join(errors, '\n'));
}

Solution 3: Bypass Validation in Test Setup Using @TestSetup

If validation rules are blocking your test's setup data, create records that satisfy the rule's conditions — don't disable the rule. Your tests should mirror real-world data scenarios.

Apex — Test Class
@isTest
private class AccountServiceTest {

    @TestSetup
    static void makeData() {
        // ✅ Include all fields validation rules require
        Account acc = new Account(
            Name          = 'Test Corp',
            Phone         = '415-555-0100', // Required by VR when Active
            Status__c     = 'Active',
            AnnualRevenue = 100000       // Must be > 0 per another VR
        );
        insert acc;
    }

    @isTest
    static void testUpdateAccount() {
        Account acc = [SELECT Id, Name FROM Account LIMIT 1];
        Test.startTest();
        acc.Name = 'Updated Corp';
        update acc;
        Test.stopTest();
        System.assertEquals('Updated Corp',
            [SELECT Name FROM Account WHERE Id = :acc.Id].Name);
    }
}

Solution 4: Use a Bypass Flag for System Automation

When a legitimate system automation (like a data migration or integration) must bypass a validation rule, the cleanest approach is to add a bypass checkbox field to the object and update the rule's formula to skip when the flag is set.

Validation Rule Formula — With Bypass
/* Original rule: fires when AnnualRevenue is blank or zero */
AND(
  ISBLANK(AnnualRevenue),
  NOT(Bypass_Validation__c)  /* Skip rule when bypass flag is true */
)
Apex — Set Bypass Flag for Data Migration
for (Account acc : accountsToMigrate) {
    acc.Bypass_Validation__c = true; // Signals rule to skip
}
update accountsToMigrate;

// Re-enable after migration
for (Account acc : accountsToMigrate) {
    acc.Bypass_Validation__c = false;
}
update accountsToMigrate;
lightbulb

Pro Tip: In Setup, go to Object Manager → [Object] → Validation Rules and use the Active checkbox filter to see all active rules at a glance. You can also temporarily deactivate a specific rule in a sandbox to confirm it's the culprit before writing any fix code — much faster than log hunting.