CoreData loadPersistentStores error

Recently I update my App a new version in App Store . What I do is only add a new Entity and add one new column to an existing Entity.Then over than 200 users run into crash when they update(Not all users run into this).

This is how I create Core Data Stack.
Code Block swift
class AppGroupLocalPersistentContainer: NSPersistentContainer {
open override class func defaultDirectoryURL() -> URL {
let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.mindo")
return storeURL!
}
}
extension NSPersistentContainer {
var url: URL? {
let url: URL? = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.mindo")
return url?.appendingPathComponent("Mindo.sqlite")
}
}
public class LocalCoreData {
deinit {
Logger.info("LocalCoreData deinit")
}
lazy var localContext: NSManagedObjectContext = {
let context = localContainer.viewContext
context.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType)
context.automaticallyMergesChangesFromParent = true
context.stalenessInterval = 0
return context
}()
lazy var localContainer: NSPersistentContainer = {
let container = AppGroupLocalPersistentContainer(name: "Mindo", managedObjectModel: NSManagedObjectModel.mergedModel(from: [Bundle.main])!)
guard let description = container.persistentStoreDescriptions.first else {
fatalError("Failed to retrieve a persistent store description.")
}
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description.setOption(false as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true
container.loadPersistentStores(completionHandler: { _, error in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
}


And here is part of crash log I copy from Xcode Organizer.

Code Block
Thread 0 name:
Thread 0 Crashed:
0 libswiftCore.dylib 0x0000000187d45cb4 _assertionFailure(_:_:file:line:flags:) + 492 (AssertCommon.swift:132)
1 libswiftCore.dylib 0x0000000187d45cb4 _assertionFailure(_:_:file:line:flags:) + 492 (AssertCommon.swift:132)
2 Mindo 0x0000000104245088 closure #1 in closure #1 in LocalCoreData.localContainer.getter + 604 (LocalCoreData.swift:39)
3 Mindo 0x00000001042449a0 thunk for @escaping @callee_guaranteed (@guaranteed NSPersistentStoreDescription, @guaranteed Error?) -> () + 64 (<compiler-generated>:0)
4 CoreData 0x000000018a3da570 -[NSPersistentStoreCoordinator _doAddPersistentStoreWithDescription:privateCopy:completeOnMainThread:withHandler:] + 1008 (NSPersistentStoreCoordinator.m:1461)
5 CoreData 0x000000018a28146c -[NSPersistentStoreCoordinator addPersistentStoreWithDescription:completionHandler:] + 268 (NSPersistentStoreCoordinator.m:1507)
6 CoreData 0x000000018a4ae880 -[NSPersistentContainer _loadStoreDescriptions:withCompletionHandler:] + 232 (NSPersistentContainer.m:284)
7 CoreData 0x000000018a289658 -[NSPersistentContainer loadPersistentStoresWithCompletionHandler:] + 316 (NSPersistentContainer.m:271)
8 Mindo 0x0000000104244d10 closure #1 in LocalCoreData.localContainer.getter + 848 (LocalCoreData.swift:36)

I know the error is occur in this line :LocalCoreData.swift:39
Code Block
fatalError("Unresolved error \(error), \(error.userInfo)")

But I have no idea how to fix this.
Post not yet marked as solved Up vote post of yueyuemax Down vote post of yueyuemax
5k views

Replies

Did you find a solution to this?
I am having almost identical crashes, but only on some devices (iPhone 7s and SE). I did not migrate any data, but I am using peristent store with descriptions. I cant recreate the crash myself.

Here is my crash log
Code Block language
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001950b6a18
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [188]
Triggered by Thread: 0
Thread 0 name:
Thread 0 Crashed:
0 libswiftCore.dylib 0x00000001950b6a18 _assertionFailure(_:_:file:line:flags:) + 492 (AssertCommon.swift:132)
1 libswiftCore.dylib 0x00000001950b6a18 _assertionFailure(_:_:file:line:flags:) + 492 (AssertCommon.swift:132)
2 SPWidgetExtension 0x0000000100471dd4 closure #1 in closure #1 in CoreDataHelper.persistentContainer.getter + 464 (CoreDataHelper.swift:153)
3 SPWidgetExtension 0x0000000100471e18 thunk for @escaping @callee_guaranteed (@guaranteed NSPersistentStoreDescription, @guaranteed Error?) -> () + 64 (<compiler-generated>:0)
4 CoreData 0x000000019775a570 -[NSPersistentStoreCoordinator _doAddPersistentStoreWithDescription:privateCopy:completeOnMainThread:withHandler:] + 1008 (NSPersistentStoreCoordinator.m:1461)
5 CoreData 0x000000019760146c -[NSPersistentStoreCoordinator addPersistentStoreWithDescription:completionHandler:] + 268 (NSPersistentStoreCoordinator.m:1507)
6 CoreData 0x000000019782e880 -[NSPersistentContainer _loadStoreDescriptions:withCompletionHandler:] + 232 (NSPersistentContainer.m:284)
7 CoreData 0x0000000197609658 -[NSPersistentContainer loadPersistentStoresWithCompletionHandler:] + 316 (NSPersistentContainer.m:271)
8 SPWidgetExtension 0x0000000100471bc4 closure #1 in CoreDataHelper.persistentContainer.getter + 620 (CoreDataHelper.swift:151)
9 SPWidgetExtension 0x00000001004717e0 CoreDataHelper.persistentContainer.getter + 40 (CoreDataHelper.swift:144)
10 SPWidgetExtension 0x00000001004657e4 context.get + 4 (CoreDataHelper.swift:27)
11 SPWidgetExtension 0x00000001004657e4 getContext + 28 (WidgetData.swift:274)
12 SPWidgetExtension 0x00000001004657e4 init + 48 (WidgetProvider.swift:21)


Anyone found the solution for this? Experiencing the same.

My loadPersistentStore completion error block is not being triggered

        container.loadPersistentStores { (description, error) in
            if let error = error {
                error.sendLog()
                fatalError(error.localizedDescription)

            }
        }

is this more of an assertion failure on coredata?

can't replicate it myself, but a few crash report happened in Testflight for some users.

  • Found the solution to my issue, it's because I was calling it on Delegate's appDidFinishLaunching and apparently not all resources have been loaded yet at that point in time.

    I had to change my persistentStore description to this:  description.shouldAddStoreAsynchronously = true         description.shouldMigrateStoreAutomatically = true         description.shouldInferMappingModelAutomatically = true

    Noticed that it only happened on iOS 15.x

    Its not the best at it means the store may create it before I did my first persistent store request. Probably adding in a queue manager will help

Add a Comment

I'm also having the same issues. Specially when the app is in background phase.

Moving this as an answer instead of a comment. Hope this helps someone experiencing the same issue

Found the solution to my issue, it's because I was calling it on Delegate's appDidFinishLaunching and apparently not all resources have been loaded yet at that point in time.

I had to change my persistentStore description to this:

description.shouldAddStoreAsynchronously = true
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true

Noticed that it only happened on iOS 15.x

Its not the best at it means the store may create it before I did my first persistent store request. Probably adding in a queue manager will help, but that's a different issue

  • May I know, how does shouldAddStoreAsynchronously able to resolve this issue? Thank you.

Add a Comment

I have the same issue.

After the test, I found out that the problem was I move storeURL to shared container(App group), and then fetch CoreData in widget extension

In most time, the app works fine. But when I change dataModel, The problem arises。

In Debug, when I run project, CoreData migrate store automatically and there is no problem, because I'm not running widget extension at this point.

In Production, when I update app from an old version, CoreDataStack container loadPersistentStores failed some time. I think both app and extension fetch sqlite file at same time case migrate failed

When I remove the code from the widget that accesses coreData, the problem goes away

I hope I can help others who are going through the same problem as me

  • Thank you!!

    I was loading the persistent store in one of the classes init method, apparently its being called on installation/update of the app. I just moved the loading of the persistent store from init to getTimeline and added in some checks.

    I'm guessing this is because main app gets loaded and calls the persistent store migration, same time as the widget calls the shared container migration

Add a Comment

For anyone looking for a solution. I fired a TSI, and now figured out what is the problem.

Reply from Apple Developer Technical Support:

When sharing a Core Data store among multiple processes, like your main app and extensions, errors can happen when multiple processes try to load the store almost at the same time, because both processes triggers the migration, which leads to a crash or data consistency. In that case, I don’t see a solution, other than avoiding multiple processes loading the store at the same time.

Then, how to avoid multiple processes loading the store at the same time?

I normally consider two options:

  • Your extensions load the store with the readonly mode, and rely on the main app to change or migrate the store.
  • If that is not possible, coordinate the processes with your own mechanism. For example, KVO + sharing UserDefaults (UserDefaults(suiteName: <App Group ID>)) to monitor changes from other process in an app group.

What I have Done to avoid this problem:

Widgets(iOS 14+):

Load the store with the readonly mode.

#if APP_WIDGET
      description.setOption(true as NSNumber, forKey: NSReadOnlyPersistentStoreOption)
#endif

Today extension(iOS 13 +)

Check if migration is required before load persistent stores. If is, load persistent stores until migration is not required. If not, load persistent stores normally.

...
if container.isNeedMigration() {
      Logger.info("Need Migration")
      #if TODAY_EXTENSION
        while container.isNeedMigration() {
          do {
            sleep(3)
          }
        }
      #endif
    }

container.loadPersistentStores
...


....
....

extension NSPersistentContainer {
  var url: URL? {
    let url: URL? = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.xxxx.xxxx.xxxx")
    return url?.appendingPathComponent("xxxxx.sqlite")
  }
}

extension NSPersistentContainer {
  func isNeedMigration() -> Bool {
    guard let url = self.url else { return false }
    if FileManager.default.fileExists(atPath: url.path) {
      do {
        let sourceMetadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: url, options: nil)
        let destinationModel = persistentStoreCoordinator.managedObjectModel
        return !destinationModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: sourceMetadata)
      } catch {
        let e = error
        Logger.info("error when check xmode compatibile", e)
      }
    }
    return false
  }
}

Hope someone find a better way to avoid multiple processes loading the store at the same time.

  • Thank you for your valuable input. May I know, is while container.isNeedMigration() workaround risky? It seems there is a possibility that we might stuck at forever loop...

Add a Comment