-
Notifications
You must be signed in to change notification settings - Fork 244
Description
GitHub Issue Draft for DLRS
Title
INVALID_ID_FIELD error when RollupJob deletes schedule items concurrently with trigger upsert
Issue Body
Description
When using Scheduled calculation mode, we occasionally encounter INVALID_ID_FIELD errors during the upsert of LookupRollupSummaryScheduleItems__c records. This occurs when the RollupJob batch is deleting schedule items at the same time a trigger is attempting to upsert new ones with the same QualifiedParentID__c.
Error Message
System.DmlException: Upsert failed. First exception on row 0; first error: INVALID_ID_FIELD, invalid record id: ()
(dlrs)
Trigger.dlrs_ReceiptDeliveryTrigger: line 7, column 1
Suspected Root Cause
We suspect this race condition may occur with the following sequence:
- T0: RollupJob starts deleting a schedule item (record may be locked)
- T1: Trigger executes upsert with same
QualifiedParentID__c- Search by external ID finds the record (not yet deleted)
- Attempts update, waits for lock
- T2: RollupJob commits deletion (record physically deleted)
- T3: Trigger's lock wait completes
- Attempts to update a now-deleted record ID
- Result: INVALID_ID_FIELD error
This appears to be a timing issue between the deletion process and the upsert operation.
Current Code Behavior
In RollupService.cls lines 1342-1361, only DUPLICATE_VALUE errors are ignored:
// iterate through errors, only return an exception for something other than DUPLICATE_VALUE
// because DUPLICATE_VALUE errors are usually sharing problems and we're happy as long as the record is in the database
for (Integer i = 0, j = results.size(); i < j; i++) {
if (!results[i].isSuccess()) {
for (Database.Error err : results[i].getErrors()) {
if (err.getStatusCode() != System.StatusCode.DUPLICATE_VALUE) {
throw new DmlException(
'Upsert failed. First exception on row ' + i +
'; first error: ' + err.getStatusCode() + ', ' +
err.getMessage() + ': ' + err.getFields()
);
}
}
}
}Proposed Solution
Treat INVALID_ID_FIELD the same as DUPLICATE_VALUE - ignore it because:
- It's a transient race condition: The schedule item will be recreated on the next trigger execution
- The parent record is already processed: If RollupJob deleted the item, it has already calculated the rollup
- Same logic as DUPLICATE_VALUE: As long as rollup processing occurs, the specific schedule item persistence doesn't matter
Suggested Code Change
for (Database.Error err : results[i].getErrors()) {
if (err.getStatusCode() != System.StatusCode.DUPLICATE_VALUE
&& err.getStatusCode() != System.StatusCode.INVALID_ID_FIELD) { // Add this
throw new DmlException(...);
}
}Thank you for considering this issue!