0

I'm very new to SwiftData and have run into an issue where I need to change a datatype in a model. I've attempted to implement a migration plan but my original schema was not of type VersionedSchema so I keep getting the following error.

Unresolved error loading container Error Domain=NSCocoaErrorDomain Code=134504 "Cannot use staged migration with an unknown model version." UserInfo={NSLocalizedDescription=Cannot use staged migration with an unknown model version.}.

This is already a released app so I'm trying not to nuke data. Can someone please guide me in the right direction to fix this?

@main
struct AuditApp: App {
    var sharedModelContainer: ModelContainer = {
        let modelConfiguration = ModelConfiguration(schema: Schema(SchemaV2.models).self, isStoredInMemoryOnly: false)

        do {                  
            return try ModelContainer(for: Schema(SchemaV2.models), migrationPlan: AuditMigrationPlan.self, configurations: [modelConfiguration])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            RootView()
                .preferredColorScheme(.light) // Force light mode
        }
        .modelContainer(sharedModelContainer)
    }
}
import Foundation
import SwiftData

enum SchemaV1: VersionedSchema {
    static var models: [any PersistentModel.Type] {
        [
            WaterSpraySystemAudit.self,
            CannonServiceInspectionReport.self,
            StripAndAssessReport.self,
            
            FileType.self,
            
            AppSettings.self
        ]
    }
    
    static var versionIdentifier: Schema.Version = Schema.Version(1, 0, 0)
}

enum SchemaV1_1: VersionedSchema {
    static var models: [any PersistentModel.Type] {
        [
            WaterSpraySystemAudit.self,
            CannonServiceInspectionReportV1_1.self,
            StripAndAssessReport.self,
            
            FileType.self,
            
            AppSettings.self
        ]
    }
    
    static var versionIdentifier: Schema.Version = Schema.Version(1, 1, 0)
}
    
enum SchemaV2: VersionedSchema {
    static var models: [any PersistentModel.Type] {
        [
            WaterSpraySystemAudit.self,
            CannonServiceInspectionReportV2.self,
            StripAndAssessReport.self,
            
            FileType.self,
            
            AppSettings.self
        ]
    }
    
    static var versionIdentifier: Schema.Version = Schema.Version(2, 0, 0)
}

enum AuditMigrationPlan: SchemaMigrationPlan {
    static var schemas: [any VersionedSchema.Type] {
        [SchemaV1.self, SchemaV1_1.self, SchemaV2.self]
    }

    static var stages: [MigrationStage] {
        [
            migrateV1toV1_1,
            migrateV1_1toV2
        ]
    }

    static let migrateV1toV1_1: MigrationStage = .custom(
        fromVersion: SchemaV1.self,
        toVersion: SchemaV1_1.self,
        willMigrate: nil,
        didMigrate: { context in
            let reports = try context.fetch(FetchDescriptor<CannonServiceInspectionReportV1_1>())
            for report in reports {
                report.ListOfPartsString = report.ListOfParts?.joined(separator: "\n")
            }
            try context.save()
        }
    )

    static let migrateV1_1toV2: MigrationStage = .lightweight(
        fromVersion: SchemaV1_1.self,
        toVersion: SchemaV2.self
    )
}

For reference this was the orignal non versioned setup

@main
struct AuditApp: App {
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([
            WaterSpraySystemAudit.self,
            CannonServiceInspectionReport.self,
            StripAndAssessReport.self,
            
            FileType.self,
            
            AppSettings.self
        ])
        let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)

        do {
            return try ModelContainer(for: schema, configurations: [modelConfiguration])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()
    
    var body: some Scene {
        WindowGroup {
            RootView()
                .preferredColorScheme(.light) // Force light mode
        }
        .modelContainer(sharedModelContainer)
    }
}
4
  • You should avoid renaming your models between versions unless it’s absolutely necessary (CannonServiceInspectionReport). Commented Sep 15 at 6:35
  • I just changed all the models to be extensions of each schema instead of global so now they all retain the model name. Commented Sep 15 at 22:15
  • Did it help with the issue or are you getting the same error? Commented Sep 16 at 6:41
  • I'm not sure if it did or not. I made those changes but it crashed under the same error. Except I ran the old schema code, it crashed, switched back to the new versioned schema code, and it ran with a successful migration. I'm waiting to test it on another device stuck with the old storage to see if it migrates its data. Commented Sep 16 at 10:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.