WidgetKit + CoreData loadPersistentStores Error

Failure to Load Persistent Stores

How are we supposed to handle this with Widgets?

I can't reproduce the issue, and in my App Target I usually just fatalError, which has resulted in very few if any crashes in production. However, since implementing my widget, I am getting hundreds of crash reports a day in my Widget target due to this. I have added logging, but have yet to receive a log or even a user complaint, so I don't know exactly what error is being produced. I am guessing it's a memory issue, or maybe a dataProtection issue.

When I build my Widget the console outputs:

[error] warning: Force checkpointing -wal while initializing query generations due to its large size (134225512)

which I assume means it's a memory issue.

I am instantiating my NSPersistentContainer in my TimeLineProvider

What is the best way to handle this? Should I just remove the fatalError?
Do I need to mirror only what's necessary from my store to a smaller json file and only share that with the widget?
Post not yet marked as solved Up vote post of mikeyM Down vote post of mikeyM
920 views

Replies

same issue ..
have you found a solution?
I'm also having similar issues!

When there's a crash in WidgetKit, it often goes unnoticed by developers and users because there's no clear indication within the widget itself. In contrast, a crash in the main app is more apparent because it causes the app to close suddenly.

One theory, as discussed in this https://developer.apple.com/forums/thread/668649, is that the main app and the widget are attempting to perform a migration simultaneously.

However, I'm skeptical of this theory because our last CoreData migration began last year. Therefore, it's surprising to see a high number of crashes after a year.

Here's where fatal error occurs. It is a pretty standard CoreData stack used in widget.

    private static func setupNSPersistentContainer() -> NSPersistentContainer {
        precondition(Thread.isMainThread)
        
        let container = NSPersistentCloudKitContainer(name: "***", managedObjectModel: NSManagedObjectModel.***)
        
        // Integrate AppGroup with CoreData. If we are assigning a new store description to CoreData, it is important
        // to finish all store description initialization, before assigning. If not, CloudKit will not work.
        let storeURL = AppGroup.wenote.containerURL.appendingPathComponent(Constants.WENOTE_SQLITE)
        let newStoreDescription = NSPersistentStoreDescription(url: storeURL)
        
        // Turn on persistent history tracking.
        newStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        newStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        
        newStoreDescription.cloudKitContainerOptions = nil
        
        // Finalize store description assigning.
        container.persistentStoreDescriptions = [newStoreDescription]
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // This is a serious fatal error. We will just simply terminate the app, rather than using error_log.
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })

Here's the info from XCode's Organizer.

Here's the crash log

Thread 0 name:
Thread 0 Crashed:
0   libswiftCore.dylib            	0x000000018d371870 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)
1   sticky-note-widgetExtension   	0x0000000104dcb890 closure #1 in static CoreDataStack.setupNSPersistentContainer() + 376 (CoreDataStack.swift:76)
2   sticky-note-widgetExtension   	0x0000000104dcb8e4 thunk for @escaping @callee_guaranteed (@guaranteed NSPersistentStoreDescription, @guaranteed Error?) -> () + 80 (<compiler-generated>:0)
3   CoreData                      	0x000000019c14a0ec -[NSPersistentStoreCoordinator _doAddPersistentStoreWithDescription:privateCopy:completeOnMainThread:withHandler:] + 668 (NSPersistentStoreCoordinator.m:1402)
4   CoreData                      	0x000000019c149df8 -[NSPersistentStoreCoordinator addPersistentStoreWithDescription:completionHandler:] + 228 (NSPersistentStoreCoordinator.m:1448)
5   CoreData                      	0x000000019c149bf4 -[NSPersistentContainer _loadStoreDescriptions:withCompletionHandler:] + 184 (NSPersistentContainer.m:291)
6   CoreData                      	0x000000019c219ff0 -[NSPersistentCloudKitContainer _loadStoreDescriptions:withCompletionHandler:] + 536 (NSPersistentCloudKitContainer.m:163)
7   CoreData                      	0x000000019c0b852c -[NSPersistentContainer loadPersistentStoresWithCompletionHandler:] + 248 (NSPersistentContainer.m:274)
8   sticky-note-widgetExtension   	0x0000000104dcbdb0 specialized static CoreDataStack.setupNSPersistentContainer() + 992 (CoreDataStack.swift:73)
9   sticky-note-widgetExtension   	0x0000000104dcb5f8 static CoreDataStack.setupNSPersistentContainer() + 4 (CoreDataStack.swift:23)
10  sticky-note-widgetExtension   	0x0000000104dcb5f8 closure #1 in CoreDataStack.persistentContainer.getter + 4 (<compiler-generated>:0)
11  sticky-note-widgetExtension   	0x0000000104dcb5f8 CoreDataStack.persistentContainer.getter + 36
12  sticky-note-widgetExtension   	0x0000000104dcb5a0 CoreDataStack.viewContext.getter + 28
13  sticky-note-widgetExtension   	0x0000000104db2058 specialized static NSPlainNoteRepository.getFirstStickyNoteWithoutTrash() + 68 (NSPlainNoteRepository.swift:54)
14  sticky-note-widgetExtension   	0x0000000104da4828 static NSPlainNoteRepository.getFirstStickyNoteWithoutTrash() + 8 (NSPlainNoteRepository.swift:22)
15  sticky-note-widgetExtension   	0x0000000104da4828 static NSPlainNoteRepository.getStickyNote(_:) + 8 (sticky_note_widget.swift:15)
16  sticky-note-widgetExtension   	0x0000000104da4828 Provider.placeholder(in:) + 64 (<compiler-generated>:0)
17  sticky-note-widgetExtension   	0x0000000104da4828 protocol witness for IntentTimelineProvider.placeholder(in:) in conformance Provider + 104
18  WidgetKit                     	0x00000001a2c65a50 IntentTimelineEntryProvider.placeholder(for:with:) + 528 (IntentConfiguration.swift:258)
19  WidgetKit                     	0x00000001a2c6a2a0 protocol witness for EntryProviding.placeholder(for:with:) in conformance IntentTimelineEntryProvider<A, B> + 24 (<compiler-generated>:0)
20  WidgetKit                     	0x00000001a2b56ef4 closure #1 in closure #2 in WidgetExtensionXPCServer.ExportedObject.getPlaceholders(requests:completion:) + 2172 (WidgetExtensionXPCServer.swift:250)
21  WidgetKit                     	0x00000001a2b5659c closure #2 in WidgetExtensionXPCServer.ExportedObject.getPlaceholders(requests:completion:) + 164 (WidgetExtensionXPCServer.swift:219)
22  WidgetKit                     	0x00000001a2c64054 thunk for @escaping @callee_guaranteed () -> () + 36 (<compiler-generated>:0)

So far, we are not able to reproduce such a crash locally.