NSPersistentCloudKitContainer CKRecord conversion errors

I'm using NSPersistentCloudKitContainer with my app and everything has been working fine for the most part. However, every now and then I come across an entity that saves fine into core data but then can't sync to cloud kit and causes the entire cloud kit feature to stop working. The error happens when starting the app and looks like this:

error: CoreData+CloudKit: -NSCloudKitMirroringDelegate _requestAbortedNotInitialized:: <NSCloudKitMirroringDelegate: 0x2820187e0> - Never successfully initialized and cannot execute request '<NSCloudKitMirroringImportRequest: 0x283a27930> 3CD51F2A-E632-4FF0-8B8C-C17DCB15A002' due to error: <CKError 0x281739a10: "Partial Failure" (2/1011); "Failed to modify some records"; uuid = 9C4B94E0-662F-4B75-894B-55AD51DE9C79; container ID = "iCloud.com.mrsdizzie.LaurasBooks"; partial errors: {
	0A2C0554-254E-47AA-B2C5-58F6C1CA038E:(com.apple.coredata.cloudkit.share.164680EE-7664-4105-9039-2FA952A013AB:__defaultOwner__) = <CKError 0x28173a6a0: "Invalid Arguments" (12/2006); server message = "Cannot create or modify field 'CD_data_ckAsset' in record 'CD_ImageData' in production schema"; op = 065A25FC65E7BB30; uuid = 9C4B94E0-662F-4B75-894B-55AD51DE9C79>
	... 3 "Batch Request Failed" CKError's omited ...
}>

The app is for keeping track of Books, so the basic data model is an entity named Book with a relationship named imageData. This maps to an entity named ImageData with a field named data. data is of type "binary data" and where the cover image for a particular book is stored. This has worked so far for hundreds of entries into core data and cloud kit, but every now and then I see an error like this in the console app and the only way to recover is delete the offending entry (either manually, or by removing the app which deletes all local data). I am now able to reproduce it with one particular entry on one device in production, but not sure how to proceed from there.

Since all of this syncing and creation of CKRecords happens automatically via NSPersistentCloudKitContainer I'm not really sure what to do, how to recover, or how to get more details about what it doesn't like in this particular case. I've monitored NSPersistentCloudKitContainer.eventNotificationUserInfoKey for event errors but only get short errors like:

CKError Domain: 2, Description: The operation couldn't be completed

The production schema is up to date and hasn't changed. Most entries into the app work fine. It is only every so often with certain entries that this error happens. There is no obvious difference between entries that I can see. The image itself in this and other cases is under 1MB.

Any advice appreciated. Thanks!

Answered by deeje in 759407022

it sure does look like CloudKit is trying to push a record containing an unidentified field: "Cannot create or modify field 'CD_data_ckAsset' in record 'CD_ImageData' in production schema"

While you may think all your image files are < 1Mb, Core Data may still be using external files in some edge cases.

You could run your app in dev mode, add a very large image > 1mb, and have it sync, then see if there are schema changes to be pushed from dev to prod?

Accepted Answer

it sure does look like CloudKit is trying to push a record containing an unidentified field: "Cannot create or modify field 'CD_data_ckAsset' in record 'CD_ImageData' in production schema"

While you may think all your image files are < 1Mb, Core Data may still be using external files in some edge cases.

You could run your app in dev mode, add a very large image > 1mb, and have it sync, then see if there are schema changes to be pushed from dev to prod?

Amazing, thank you! I did just that and it did offer to push CD_data_ckAsset from development to production afterwards. I knew that it automatically created ckAsset for larger files, but had not occurred to me at all that this never came up in the development environment and so wasn't pushed to production. The error seems more obvious now! The offending image was 756534 bytes but Core Data must have decided to use an external file anyway.

Thanks again I really appreciate it!

Instead of doing as the above comment, use NSPersistentCloudKitContainer.initializeCloudKitSchema() instead.

  1. Do it on a physical device
  2. Do it to sandbox environment
  3. Deploy changes to production

There will likely be more changes than you're expecting if you've previously been relying on it auto-creating, but that should be fine.

@CrunchyBagel Thank you! That is also helpful. I wasn't aware that initializeCloudKitSchema() was different than just manually promoting from development to production after creating test records within the App but I see what you mean now. I thought that NSPersistentCloudKitContainer created all necessary records in the development environment based on whatever is defined inxcdatamodeld as part of how it works and you then later promote those to production. I see it only creates records based on the specific data that has been uploaded which isn't going to include optional _ckAsset records and other things unless those were specifically needed for the test data.

Again, much appreciated!

NSPersistentCloudKitContainer CKRecord conversion errors
 
 
Q