SwiftData Migration Fail: What kind of backing data is this?

I'm trying to test migration between schemas but I cannot get it to work properly. I've never been able to get a complex migration to work properly unfortunately. I've removed a property and added 2 new ones to one of my data models.

This is my current plan.

enum MigrationV1toV2: SchemaMigrationPlan {
    static var schemas: [any VersionedSchema.Type] {
        [SchemaV1.self, SchemaV2.self]
    }
    
    static let migrateV1toV2 = MigrationStage.custom(
        fromVersion: SchemaV1.self,
        toVersion: SchemaV2.self,
        willMigrate: { context in
            
            print("Inside will migrate")
            
            // Get old months
            let oldMonths = try context.fetch(FetchDescriptor<SchemaV1.Month>())
            print("Number of old months:\(oldMonths.count)")
            
            for oldMonth in oldMonths {
                // Convert to new month
                let newMonth = Month(name: oldMonth.name, year: oldMonth.year, limit: oldMonth.limit)
                print("Number of transactions in oldMonth: \(oldMonth.transactions?.count)")
                print("Number of transactions in newMonth: \(newMonth.transactions?.count)")
                
                // Convert transactions
                for transaction in oldMonth.transactions ?? [] {
                    // Set action and direction
                    let action = getAction(from: transaction)
                    let direction = getDirection(from: transaction)
                    
                    // Update category if necessary
                    var category: TransactionCategory? = nil
                    if let oldCategory = transaction.category {
                        category = TransactionCategory(
                            name: oldCategory.name,
                            color: SchemaV2.Category.Colors.init(rawValue: oldCategory.color?.rawValue ?? "") ?? .blue,
                            icon: getCategoryIcon(oldIcon: oldCategory.icon)
                        )
                        
                        // Remove old category
                        context.delete(oldCategory)
                    }
                    
                    // Create new
                    let new = Transaction(
                        date: transaction.date,
                        action: action,
                        direction: direction,
                        amount: transaction.amount,
                        note: transaction.note,
                        category: category,
                        month: newMonth
                    )
                    
                    // Remove old transaction from month
                    oldMonth.transactions?.removeAll(where: { $0.id == transaction.id })
                    
                    // Delete transaction from context
                    context.delete(transaction)
                    
                    // Add new transaction to new month
                    newMonth.transactions?.append(new)

                }
                
                // Remove old month
                context.delete(oldMonth)
                
                print("After looping through transactions and deleting old month")
                print("Number of transactions in oldMonth: \(oldMonth.transactions?.count)")
                print("Number of transactions in newMonth: \(newMonth.transactions?.count)")
                
                // Insert new month
                context.insert(newMonth)
                
                print("Inserted new month into context")
            }
            
            // Save
            try context.save()
             
        }, didMigrate: { context in
            print("In did migrate")
            
            let newMonths = try context.fetch(FetchDescriptor<SchemaV2.Month>())
            print("Number of new months after migration: \(newMonths.count)")
        }
    )
    
    static var stages: [MigrationStage] {
        [migrateV1toV2]
    }
}

It seems to run fine until it gets the the line: try context.save(). At this point it fails with the following line:

SwiftData/PersistentModel.swift:726: Fatal error: What kind of backing data is this? SwiftData._KKMDBackingData<Monthly.SchemaV1.Transaction>

Anyone know what I can do about this?

Can you show us your SchemaV1 and SchemaV2, and explain what you're trying to do? It looks to me like you're trying to manually create a SchemaV2.Month and a SchemaV2.Transaction in the willMigrate, which is probably not what you want.

SwiftData Migration Fail: What kind of backing data is this?
 
 
Q