A Fatal Bug in iOS App, Developer’s Nightmare, and Caffeine!

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.

Problem Description

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)

Data Model Zitrr Camera 1.1

and this is the Core Data Model of v1.3(Updated One)

Data Model Zitrr Camera 1.3

Notice that I have created only one Entity “ZNCAsset” in the project.

Possible Approaches

  • 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

addPersistentStoreWithType:configuration:URL:options:error:

with these options

NSMigratePersistentStoresAutomaticallyOption, NSInferMappingModelAutomaticallyOption.

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

mergedModelFromBundles:forStoreMetadata:

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.

Stuck :( !

Solution, “From no luck to luck”!

I started debugging at v1.3. When I printed metadata of the store by using

NSPersistentStoreCoordinatormetadataForPersistentStoreOfType:NSSQLiteStoreTypeURL:url error:&error

it looked like

Data Model Entities in Zitrr Camera 1.1

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 

Bingo!

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.

Root Cause

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!

Posted in Zitrr Camera | 2 Comments