Crash during batch deletion merge when positive fractional decimals are stored and used in a derived attribute

I am experiencing a crash when performing a batch delete and merging changes on a Core Data store that uses NSPersistentCloudKitContainer. The crash appears to be triggered when positive fractional Decimal values are stored in a TransactionSplit entity (those values are aggregated via a derived attribute in the AccountTransaction entity). If I store whole numbers or negative fractional decimals, deletion seems to work correctly. I suspect that the issue is related to the internal representation of positive fractional decimals in conjunction with a derived attribute.

Data Model Setup:

  • Account (1:N relationship → AccountTransaction)
  • AccountTransaction (1:N relationship → TransactionSplit), which contains a derived attribute (e.g., “splits.amount.@sum”) that computes the sum over the “amount” attribute on its related TransactionSplit objects.
  • TransactionSplit, which contains a stored Decimal attribute named “amount” (of type Decimal/NSDecimalNumber).

Steps to Reproduce:

  1. Insert sample data where each TransactionSplit’s “amount” is set to a positive fractional value (e.g., 1000.01), by using code similar to:
func createSampleData() {
  // Execute all creation on the context’s queue.
  let checkingAccount = Account(context: context)
  checkingAccount.id = UUID()
  checkingAccount.name = "Main Checking"
  let randomTransactionCount = 1000
  for _ in 0..<randomTransactionCount {
    let transaction = AccountTransaction(context: context)
transaction.id = UUID()
    transaction.account = checkingAccount
    let randomValue = Double.random(in: 5...5000)
    let decimalValue = NSDecimalNumber(value: randomValue)

    let split1 = TransactionSplit(context: context)
    split1.id = UUID()
    split1.amount = decimalValue
    split1.transaction = transaction

    let split2 = TransactionSplit(context: context)
    split2.id = UUID() 
    split2.amount = decimalValue
    split2.transaction = transaction
  }
  save()
}
  1. The AccountTransaction’s derived attribute automatically aggregates the sum of its related TransactionSplit amounts.
  2. Perform a batch deletion using NSBatchDeleteRequest (with resultType set to .resultTypeObjectIDs) on your entities and merge the changes back into your main context:
private func delete(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
  let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
  batchDeleteRequest.resultType = .resultTypeObjectIDs

  // ⚠️ When performing a batch delete we need to make sure we read the result back
  // then merge all the changes from that result back into our live view context
  // so that the two stay in sync.
  if let delete = try? context.execute(batchDeleteRequest) as? NSBatchDeleteResult {
    let changes = [NSDeletedObjectsKey: delete.result as? [NSManagedObjectID] ?? []]
    NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [context])
  }
}
  1. Save the context after deletion.
Answered by DTS Engineer in 828480022

Thanks. Yeah, this is pretty much the same as the known issue I mentioned (r.96632321), which happens when derived attribute @sum + Decimal is used.

I’d still suggest that you file your own feedback report to hopefully draw more attentions – If you do so, please share your report ID here for folks to track.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

This is pretty similar to an existing issue we know. Would you mind to try the following?

  1. Replace NSPersistentCloudKitContainer with NSPersistentContainer and verify that the issue is still there. This is to simplify the issue by ruling out CloudKit.

  2. Reproduce the issue, gather a crash report, and share here.

I'd be able to confirm by reading the crash report.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

After replacing NSPersistentCloudKitContainer with NSPersistentContainer, I'm still getting the crash, as you suspected. Attached is the crash report when I ran the code on the simulator.

Accepted Answer

Thanks. Yeah, this is pretty much the same as the known issue I mentioned (r.96632321), which happens when derived attribute @sum + Decimal is used.

I’d still suggest that you file your own feedback report to hopefully draw more attentions – If you do so, please share your report ID here for folks to track.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Thank you. Yes, I have submitted a feedback report. Here's the ID: FB16507733.

For now, since I'm storing dollar amounts in this field, I've switched to using an int data type to take advantage of base-10 representation, and I'm just storing cents. Then in my extension, I'm handling the conversion with a property set/get.

Crash during batch deletion merge when positive fractional decimals are stored and used in a derived attribute
 
 
Q