I was pulling my hair out over the “Cannot find model for source store” and “Cannot create an NSMigrationManager with a nil source model” error for a whole day.
If you have never faced a database migration problem in Objective-C, you might be thinking ‘what the hell is he talking about?’. Well, we recently faced this deadly bug that crashed Zitrr Camera on launch after the v1.3 update. For most users, after the update, the app just won’t launch. We have received endless emails and bug tickets and crash reports from our users. All complaining about the same.
For obvious reasons, this was intolerable. I could see my teammates standing around me with bamboos in their hands! So, this is a post on what went wrong, why it went wrong and how I fixed it.
As you’d know, Zitrr Camera was due for an update, v1.3. Now in v1.3, I was trying to run core data migration for adding some more fields to the internal database. But it seemed that the compiler was unable to find the source data model. Somehow, even though I had added the data model file and configured it correctly, the compiler just couldn’t find it.
I searched Google and Stackoverflow for some answers, tried many other things, all without any luck.
Here is the Core Data Model of v1.1(Old One)
and this is the Core Data Model of v1.3(Updated One)
Notice that I have created only one Entity “ZNCAsset” in the project.
Core Data Versioning and Migration to do it automatically.
I created a new version of the model, set it as the current version and called
with these options
but no luck.
Since the automatic migration didn’t seem to work in any way, I tried manual migration.
I extracted the metadata and checked if the model is compatible to the new one. Then I found a suitable source model for the store via
Same as before, the source model was still nil.
Maybe I should delete the old model.
I can’t delete the old data model and start fresh! I need to migrate customer’s data from v1.1.
Solution, “From no luck to luck”!
I started debugging at v1.3. When I printed metadata of the store by using
it looked like
But I had created only one Entity “ZNCAsset” in Zitrr Camera. From where did these TKBlog, TKPhoto, TKChat … TKUser, etc. came from? I didn’t have any data model in v1.3 that described Entities like TKBlog, TKPhoto, etc. So I opened the project of v1.1 and searched there and
Actually, in v1.1 I had used a third party library “TumblrAPI”, which had a file “TumblrKit.xcdatamodeld”, which had Entities like TKBlog, TKPhoto, etc. As we dropped support of Tumblr in v1.3, I deleted all files from the project related to TumblrAPI including the TumblrKit.xcdatamodeld.
As a result, I have now added back only the file TumblrKit.xcdatamodeld to v1.3 and updated v1.1 with the new build and
Voila! It works!
it just started working fine like old days.
It occurred due to a side effect of
NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:sourceMetadata];
which created a model containing Entities from the main model as well as any other model present in the application (here, TumblrAPI’s Model). The above code pulled all extra Entities from TumblrAPI’s model in v1.1 and stored it as a part of metadata of the PersistentStore, but now when in v1.3 the new source model is created using
NSManagedObjectModel *sourceModel = [NSManagedObjectModelmergedModelFromBundles:nil forStoreMetadata:sourceMetadata];
the compiler is unable to find the source model for the other missing entities. As the metadata of the source store has those TumblrAPI’s Entities information, but does not have the Data Model TumblrKit.xcdatamodeld file in v1.3 it was unable to create the source model from the source store.
Hence, the crash.
I’m sure you would have guessed by now what it takes to fix fatal bugs like that. With green bamboos around, for me it was a sense of urgency, some grit, and unlimited caffeine
Thanks for reading!