function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
tantoniotantonio 

Update failed. First exception on row 0; first error: MISSING_ARGUMENT, Id not specified in an update call

I am trying to figure out how to pass the ID of an existing record I am trying to update. I get the above error in the debug logs after running this method.

As a background, I have a trigger after update running the passes trigger.new into a method called MarqueeUpdate. From there, I query to find the existing ChangeRecord__c. I need the ID of that ChangeRecord__c to update. 

I cannot figure out how to pass the id of that record to my update statement. 
//Updating existing records
    public static void MarqueeUpdate(List<NI_MarqueeFeature__c> marqueeUpdate){ 
        
        //marqueeUpdate contains trigger.new
        for (NI_MarqueeFeature__c mi : marqueeUpdate){
            String Id = mi.Id;
            List <ChangeRecord__c>  upMarquee = [SELECT ID
                    				 FROM ChangeRecord__c
                				 WHERE ChangeRecord__c.ID__c = :Id];
            
                    if (marqueeUpdate.size()>0) {
                        ChangeRecord__c um = new ChangeRecord__c ();
                        
                        um.ID__c = mi.id;
                        um.LastMod__c = mi.LastModifiedDate;
                        
                        upMarquee.add(um);
                        
                        try {
                            update um;
                          } catch (system.DmlException e) {
                            system.debug (e);}
        }
        }
    }

Best Answer chosen by tantonio
Nick WhitneyNick Whitney
Understood on Validating after. I added some notes on a line by line level. This should work a little better. Let me know if you have any open questions or want to discuss. 

List <ChangeRecord__c> updatedChangeRecords = new List <ChangeRecord__c>(); // Needed to bulkify the Code
for (NI_MarqueeFeature__c mi : marqueeUpdate){
//String Id = mi.Id; // Removing as established in query
ChangeRecord__c updateChangeRecord = [SELECT ID, LastMod__c
    FROM ChangeRecord__c
    WHERE ChangeRecord__c.ID__c = :mi.Id LIMIT 1];
//if (marqueeUpdate.size()>0) { // This line shouldn't be needed. Can't iterate over an empty list
//ChangeRecord__c um = new ChangeRecord__c (); Don't need a new record, updating existing
//um.ID__c = mi.id; // Removing as established in query
updateChangeRecord.LastMod__c = mi.LastModifiedDate; // Changed Variable Name
updatedChangeRecords.add(updateChangeRecord); // Changed Variable Name

  /*
  try {
   update um;
  }
  catch (system.DmlException e) {
   system.debug (e);
  }*/
//}
}

// See https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_database.htm#apex_System_Database_update
Database.SaveResult[] srList = Database.update(updatedChangeRecords, false);

// See https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_database_saveresult.htm#apex_methods_system_database_saveresult
for (Database.SaveResult sr : srList) {
    if (sr.isSuccess()) {
        // Operation was successful, so get the ID of the record that was processed
        System.debug('Successfully updated ChangeRecord Id: ' + sr.getId());
    }
    else {
        // Operation failed, so get all errors              
        for(Database.Error err : sr.getErrors()) {
            System.debug('The following error has occurred.');                  
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('Fields that affected this error: ' + err.getFields());
        }
    }
}

All Answers

Ramu_SFDCRamu_SFDC
The problem is in line # 14 where you mentioned 'um.ID__c where as the update call expects a standard id to be passed.

Change line # 14 to um.ID=mi.id which will fix the issue

Please mark this as the best answer if it resolved your issue.
tantoniotantonio
Hi Ramu,

Thanks for the response.

The problem is there are two objects at play. When NI_MarqueeFeature__c object records are updated I need to modify a cooresponding record in ChangeRecord__c object.

So um.id is actually not mi.id because they are records from different objects. um.ID__c is a custom fieild on ChangeRecord__c object that is used to create the relationship.

Please let me know your thoughts.
Nick WhitneyNick Whitney
I am a little unclear if you are attempting to insert new ChangeRecord__c objects in lines 12 to 20 or update existing records. The answer is that you are trying to update (Line 20) a new record (Line 12). You need to either do an insert, which will work as is if you change line 20 or to do an insert or an update and then you need to retrieve a record, update it and then save. 

Can you describe more about what you are trying to do with the code?


tantoniotantonio
Hi Nick,

Its the second option. I need to retrieve the record. That is what this query is doing:

List <ChangeRecord__c>  upMarquee = [SELECT ID
                    		     FROM ChangeRecord__c
                		     WHERE ChangeRecord__c.ID__c = :Id];

The :Id variable in the where clause contains the id I need to see if there is an existing record in ChangeRecord__c.

If there is, then I need to update that record with some new values. That query does return 1 record, just like it should. I need to then get the ID of that returned record to do the DML further down in the method.

Hope that helps!
Nick WhitneyNick Whitney
Will there only ever be a single record? Or can there be multiple records?
tantoniotantonio
There will only ever be one record. I'll write validation around that after I get this working.
Nick WhitneyNick Whitney
Understood on Validating after. I added some notes on a line by line level. This should work a little better. Let me know if you have any open questions or want to discuss. 

List <ChangeRecord__c> updatedChangeRecords = new List <ChangeRecord__c>(); // Needed to bulkify the Code
for (NI_MarqueeFeature__c mi : marqueeUpdate){
//String Id = mi.Id; // Removing as established in query
ChangeRecord__c updateChangeRecord = [SELECT ID, LastMod__c
    FROM ChangeRecord__c
    WHERE ChangeRecord__c.ID__c = :mi.Id LIMIT 1];
//if (marqueeUpdate.size()>0) { // This line shouldn't be needed. Can't iterate over an empty list
//ChangeRecord__c um = new ChangeRecord__c (); Don't need a new record, updating existing
//um.ID__c = mi.id; // Removing as established in query
updateChangeRecord.LastMod__c = mi.LastModifiedDate; // Changed Variable Name
updatedChangeRecords.add(updateChangeRecord); // Changed Variable Name

  /*
  try {
   update um;
  }
  catch (system.DmlException e) {
   system.debug (e);
  }*/
//}
}

// See https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_database.htm#apex_System_Database_update
Database.SaveResult[] srList = Database.update(updatedChangeRecords, false);

// See https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_database_saveresult.htm#apex_methods_system_database_saveresult
for (Database.SaveResult sr : srList) {
    if (sr.isSuccess()) {
        // Operation was successful, so get the ID of the record that was processed
        System.debug('Successfully updated ChangeRecord Id: ' + sr.getId());
    }
    else {
        // Operation failed, so get all errors              
        for(Database.Error err : sr.getErrors()) {
            System.debug('The following error has occurred.');                  
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('Fields that affected this error: ' + err.getFields());
        }
    }
}
This was selected as the best answer
tantoniotantonio
Wow, thanks so much. What you have here makes total sense.

I only had to make a small change to get it to work: 

List <ChangeRecord__c>  updatedChangeRecord  = [SELECT ID, LastMod__c FROM ChangeRecord__c WHERE ChangeRecord__c.ID__c = :mi.Id LIMIT 1];
						
                        updatedChangeRecord[0].LastMod__c = mi.LastModifiedDate;//I had to add [0] here
                        
            
                        updatedChangeRecords.add(updatedChangeRecord[0]);// and the same here

Thanks again. This is working now :-)
SmartPlayerSmartPlayer
Thanks Ramu. You saved my lot of time :)