SwiftData Crashes After Modifying The VersionedSchema More Than Once

I've been stuck on this one for quite a while now, and I'm starting to become more and more convinced this is an issue with Xcode 15 Beta RC.

Just to give you some context I seem to be getting the following crash after modifying my schema (adding new properties) for the the second time. Below is the crash that is occurring on my device & simulator.

Unresolved error loading container Error Domain=NSCocoaErrorDomain Code=134130 "Persistent store migration failed, missing source managed object model." UserInfo={URL=file:///Users/xxxxx/Library/Developer/CoreSimulator/Devices/23B8CDDD-CC5F-4A1C-B0F4-CF89C77B7ECF/data/Containers/Data/Application/235A14D7-6492-439F-BB4D-B18498D80970/Library/Application%20Support/default.store, metadata={
    NSPersistenceFrameworkVersion = 1327;
    NSStoreModelVersionChecksumKey = "dia3s8Q2+lqw669j9+RcPLQ+06yu0x6BBTZ4cXoQ1os=";
    NSStoreModelVersionHashes =     {
        Category = {length = 32, bytes = 0x187754bb 36c51a62 85ede16f 4b2a3912 ... 57326030 2de7ef77 };
        Item = {length = 32, bytes = 0xa7e4be4d ddd86d36 f71799b0 bc69dcb4 ... 83d47dfe d433fc01 };
    };
    NSStoreModelVersionHashesDigest = "G/Tk4lzyeNBXzf5+7qxbd+isF8uFnSaC5LtUCCkC8GQwaG1d9Di0eJ10NQEyPgwRczoYeYAMYG8ai4RooEhH9w==";
    NSStoreModelVersionHashesVersion = 3;
    NSStoreModelVersionIdentifiers =     (
        "1.2.0"
    );
    NSStoreType = SQLite;
    NSStoreUUID = "A99894EA-FA7B-4CA7-AEB7-6DEE42843EC0";
    "_NSAutoVacuumLevel" = 2;
}, reason=Can't find model for source store}

I currently have 5 versions of my Schemas there's two of them

  • Item
  • Category

Below is a minified changelog of what has changed between versions.

  • Version 1 (Initial Version)
  • Version 2 (Lightweight Migration - Property is renamed in Item)
  • Version 3 (Custom Migration - New Property is added to Item both are bools)
  • Version 4 (Custom Migration - New Property is added to Category which is a transformable)
  • Version 5 (Custom Migration - New Property is added to Item which is a string)

It's quite a large file with all of the version schema's etc so i've created a gist here for you to see all of the changes that have been made between Version 1 up until Version 5.

The problem that I'm seeing is that between migration for V1 up until V4 everything is fine. It's only until SwiftData attempt to migrate V4 to V5 and I get the crash that I have provided above, and V5 only has a new string property which shouldn't be causing a crash since I've done 2 custom migrations that were all fine before V5 so this seems really strange even tho my migration plan is setup properly which you can see below.

enum ToDosMigrationPlan: SchemaMigrationPlan {
    static var schemas: [VersionedSchema.Type] {
        [ToDosSchemaV1.self,
         ToDosSchemaV2.self,
         ToDosSchemaV3.self,
         ToDosSchemaV4.self,
         ToDosSchemaV5.self]
    }
    
    static var stages: [MigrationStage] {
        [
            migrateV1toV2,
            migrateV2toV3,
            migrateV3toV4,
            migrateV4toV5
        ]
    }
    
    // V1 to V2
    static let migrateV1toV2 = MigrationStage.lightweight(
        fromVersion: ToDosSchemaV1.self,
        toVersion: ToDosSchemaV2.self
    )
    
    // V2 to V3
    static let migrateV2toV3 = MigrationStage.custom(
        fromVersion: ToDosSchemaV2.self,
        toVersion: ToDosSchemaV3.self,
        willMigrate: nil,
        didMigrate: { context in
            
            let items = try? context.fetch(FetchDescriptor<ToDosSchemaV3.Item>())
            
            items?.forEach { item in
                item.isFlagged = false
                item.isArchived = false
            }
            
            try? context.save()
        })
    
    static let migrateV3toV4 = MigrationStage.custom(
        fromVersion: ToDosSchemaV3.self,
        toVersion: ToDosSchemaV4.self,
        willMigrate: nil,
        didMigrate: { context in
            
            let categories = try? context.fetch(FetchDescriptor<ToDosSchemaV4.Category>())
            categories?.forEach { category in
                category.color = UIColor(possibleColors.randomElement()!)
            }
            
            try? context.save()
            
        })
    
    static let migrateV4toV5 = MigrationStage.custom(
        fromVersion: ToDosSchemaV4.self,
        toVersion: ToDosSchemaV5.self,
        willMigrate: nil,
        didMigrate: { context in
            
            // TODO: Handle setting some custom data here with defaults

        })
}

Has anyone come across this or got any ideas as to what the problem may be?

Answered by tundsdev in 765727022

I've managed to figure it out after like 4 hours... If you're working with migrations and adding in transformable properties make sure they are optional by default...I'm not too sure if this is by design. But after making my transformable properties optional my migrations started to work again.

Here is the entire migrations log attached

So i've managed to nail down that the migration is crashing from V3 because I've added a transformable property...It's like it can't find the store after you add a transformable property and crashes. If I make the transformable property @Transient it will clear all of my data and won't crash but it does clear the entire storage like it's a brand new migration.

Accepted Answer

I've managed to figure it out after like 4 hours... If you're working with migrations and adding in transformable properties make sure they are optional by default...I'm not too sure if this is by design. But after making my transformable properties optional my migrations started to work again.

Hello, this is not a problem with Xcode as you found out, but with the data that already exists in your database. Suppose you have 5 fields and some records in the database. You are adding a field that is NOT optional. What should happen to the records where the field is empty? However, the field cannot be empty. There are various strategies to deal with this, but I'm not sure it's easy with core data.

SwiftData Crashes After Modifying The VersionedSchema More Than Once
 
 
Q