The problem I am facing is that the DML operation is being executed and a record Id is generated for the newly inserted record but when I try to query the record or access it in Salesforce, it does not exist. I think the usage of AddError is causing this problem. How should I solve this problem?

trigger duplicateLeadHandler on Lead (before insert) {
    List <String> nationalIdList = new List<String>(); //list of all national ids
    List<Invalid_Lead__c> invalids = new List<Invalid_Lead__c>(); //list of invalid leads to be inserted
    for (Lead ld:trigger.new) {
     nationalIdList.add(ld.National_ID__c); //adds all national ids from new leads to be inserted
    List <Lead> leadList = new List<Lead>();
    leadList = [SELECT National_ID__c FROM Lead WHERE National_ID__c in :nationalIdList]; //fetch duplicate national ids from existing leads
    for (Lead ld:trigger.new) { //compare for duplicates
        If (leadList.size() > 0) {
            // Displaying the error on field
            ld.National_ID__c.addError( 'Lead already exists. Added to Invalid Leads.' ); 
            //I think addError is the problem since it seems to block DML operations
            Invalid_Lead__c invalid = new Invalid_Lead__c ();
            System.debug('Create invalid lead');
            System.debug('lead national id: ' + ld.National_ID__c);
            System.debug('lead phone: ' + ld.Phone);
            System.debug('lead email: ' + ld.Email);
            invalid.National_ID__c = ld.National_ID__c;
            invalid.Phone__c = ld.Phone;
            invalid.Email__c = ld.Email;    
            System.debug('invalid lead details: ' + invalid);
            System.debug('Added to list');
        try {
            insert invalids; //this statement isn't inserting records into Salesforce but it does execute
            System.debug('Invalid leads inserted');
        catch (Exception Ex){
            system.debug('Insertion failed: ' + Ex);
  • also, where you have the comment 'compare for duplicates' you're not actually comparing the trigger.new list with the existing lead list... only checking the size of the existing lead list.
    – edralph
    Mar 5, 2021 at 23:02

1 Answer 1


Your comment is correct:

//I think addError is the problem since it seems to block DML operations

That's more or less exactly what it does. It prevents that record from being inserted, and if the originator of the DML operation has not specified allOrNone=False, it will throw a DmlException that will cause the entire transaction to be rolled back.

You cannot use both addError() and perform DML in a trigger and expect it to work consistently for that very reason. Unless, again, the originator of the record insert operation did so with the option to allow partial success, your addError() is just going to cause an exception and a rollback. This is an example of a more general principle that you cannot trivially "convert" an in-progress DML operation to either another DML operation or an operation on some other record.

If you must pursue this paradigm, you could delete the duplicate lead records rather than using addError(). But I would suggest instead using out of the box Duplicate Management and considering whether storing data that you explicitly label as invalid is worth the implementation costs.

You should never do this:

        catch (Exception Ex){
            system.debug('Insertion failed: ' + Ex);

It risks your data integrity and makes debugging difficult to impossible because you're deliberately suppressing all errors.

  • Thank you for the quick reply. Makes a lot of sense now.
    – user93687
    Mar 5, 2021 at 22:14

You must log in to answer this question.