Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Apex

System.DmlException: Insert failed (or Update / Upsert / Delete failed)

A DML statement (insert/update/upsert/delete) failed. The exception message contains a "first exception on row N" line that tells you which record blew up and why — that's where you actually look.

Also seen asDmlException·Insert failed·Update failed·Upsert failed

DmlException is the umbrella exception for any failure during insert, update, upsert, delete, merge, or their Database.* equivalents. Useful diagnostic info is buried inside its message, not the type name.

Read the right part of the message

System.DmlException: Insert failed. First exception on row 2;
first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Email]: [Email]

There are three pieces:

PartMeaning
Insert failedWhich DML operation
row 2The 0-indexed position of the failing record in the list you passed
REQUIRED_FIELD_MISSING ...The actual reason — almost always a known Salesforce error code

Look up the inner code (REQUIRED_FIELD_MISSING, FIELD_CUSTOM_VALIDATION_EXCEPTION, INSUFFICIENT_ACCESS_OR_READONLY, etc.) — that's the page that explains your specific failure.

The hidden problem: all-or-nothing

By default, insert myList is all-or-nothing: if record 2 fails, records 0 and 1 also roll back. In a 200-record bulk operation, one bad row can trash 199 good ones.

If you want partial success (commit the good rows, collect errors for the bad ones), use the Database.* overloads with allOrNone = false:

Database.SaveResult[] results = Database.insert(myList, false);

for (Integer i = 0; i < results.size(); i++) {
    Database.SaveResult sr = results[i];
    if (!sr.isSuccess()) {
        for (Database.Error err : sr.getErrors()) {
            System.debug(
                'Row ' + i + ' (' + myList[i].Id + '): ' +
                err.getStatusCode() + ' — ' + err.getMessage()
            );
        }
    }
}

Now you get a per-row report instead of one fatal exception.

Trapping the exception cleanly

If you do want to halt on any failure, at least log richly:

try {
    insert myList;
} catch (DmlException e) {
    for (Integer i = 0; i < e.getNumDml(); i++) {
        System.debug(
            'Row ' + e.getDmlIndex(i) +
            ' status: ' + e.getDmlStatusCode(i) +
            ' message: ' + e.getDmlMessage(i) +
            ' fields: ' + e.getDmlFieldNames(i)
        );
    }
    throw e;
}

The getDml* family is the structured version of the human-readable message. Use it when you're surfacing errors to a Lightning component or logging to a custom error table.

A common cause that isn't a validation rule

If the inner code is INSUFFICIENT_ACCESS_OR_READONLY and you're sure the user has CRUD on the object, check:

  • Field-Level Security on each updated field
  • A formula field accidentally listed in the SELECT/UPDATE
  • A record-level sharing rule the user doesn't satisfy
  • An AuraEnabled method that didn't declare with sharing and is now running with elevated permissions you didn't intend

Related dictionary terms