Error Handling, Savepoints, and Inserts
I’ve been working with Apex for a little over two years now and I still learn little tips and tricks all the time.
Today I ran in to a somewhat peculiar problem when trying to catch errors on the insertion of a record. Here is the scenario in super pseudo apex code.
1) Set a database save point with Apex
2) Insert a record with Apex
3) Some type of validation error prevents the record from being inserted
4) Using a try-catch statement catch the error and display it to user
5) Roll back to your Database savepoint
6) Allow the user to fix the error.
7) When the save occurs the second time I would receive this error: “cannot specify Id in an insert call”
Huh, wait….what? The insert failed because of the validation rule, right? Kinda, sort of, it’s not really clear. Even though the insert failed my object in memory was still being assigned an Id. This caused a problem when trying to insert the second time.
I’m guessing salesforce.com sets the ID of a record before the insert as you can’t set values after inserts as the object would become read-only. Similar to how triggers work, you can only write values before inserts and updates, not after. When the operation fails the Id in the code is not removed. This is a giant guess on how the process works and it could be totally wrong.
So how to get around this problem? The solution is fairly simple. In the catch section of the code we want to clone the record without preserving the Id and assign this clone back to the original object. Something like this:
Savepoint sp = Database.setSavepoint(); try{ insert object; }catch(exception e){ Database.rollback(sp); object = object.clone(false); return null; }
The false parameter in the clone method makes an exact copy of the object without preserving the Id. So the next time the user attempts to save, the Id is null, and there should be no issues.

Awesome article. I’ve had the same issue before, but didn’t solve it as cleanly as you’ve done.
Nice article. Is it possible to update a field of any object inside trigger and then based on some condition, addError() to display an error message to user? But the update to the field should be saved .
Pseudo code
lead.status=’DupeFound’; –this should be saved even if there is an errror!
if(lead.customfield == ‘Dupe’)
lead.adderror(‘cannot convert dupe’);
–other code