Fixing Core Data Lightweight Migration Crashes From A Missing Model Version

July 8, 2014

Have you ever made many changes to your Core Data model layer without first making a new model version? I recently did just that and wanted to document the easy steps to put your project back on track. First, there are two assumptions:

  1. Your changes are compatible with Core Data's built-in Lightweight Migration.
  2. The project is tracked in a source control system (Git preferably, but any other SCM will get the job done).

The Scenario: You have shipped a 1.0 version of your Core Data app, and the data model is looking great. After making sure the launch goes smoothly, you've envisioned some great new features for the next version and are so excited that you dive right into the xcdatamodeld file to start making the necessary model changes. Things are great: the next version's code is compiling, the new features work as intended, and you start to do some more extensive testing before wrapping it up. Unfortunately, as you test the upgrade path from 1.0 to the new version, you crash as you hit code paths that exercise the new model changes. Although your changes are compatible with Lightweight Migration, it isn't triggered unless the version of the data model changes; thus, your store is still in the structure of the 1.0 data model and blows up when it sees the newer entities, attributes, or relationships.

The Fix: Source control to the rescue! The labor intensive fix is to revert to the 1.0 xcdatamodeld file, version the data model in Xcode, and manually apply the needed changes to the new version. This is decidedly error-prone if you forget a change. Luckily the easy fix is a lot less work and 100% reliable:

  1. Save a copy of the new version's xcdatamodeld file somewhere outside of source control.
  2. Revert to the 1.0 version of the xcdatamodeld file.
  3. Create a new model version in Xcode using Editor > Add Model Version...
  4. Rename the xcdatamodeld copy you saved in Step 1 to the file generated by Step 3.
  5. Copy & paste the renamed file from Step 4 on top of the file generated by Step 3.
  6. Test the upgrade path again to ensure the migration happens smoothly.
  7. Check in your changes and continue with development.

If your changes didn't meet the requirements for Lightweight Migration, the above steps will still work, but there is an extra step after Step 5:

  1. Create a mapping model to explicitly tell Core Data how to do the migration.
  2. Test the upgrade path again to ensure the migration happens smoothly.
  3. Check in your changes and continue with development.