This is a long post, so let me start with a summary: I am attempting to implement what "ought to be" a simple SwiftData migration, and am receiving the following fatal error from the ModelContainer initializer:
NSCocoaErrorDomain Code=134504 "Cannot use staged
migration with an unknown model version."
The crash occurs both in the Simulator and on a physical device.
Both the original schema and the new schema load and run as expected if loaded from scratch — so I conclude the Models are OK; it is the migration from the original schema to the new schema which is the issue.
I have reported this as FB22652791 and Technical Incident Case # 19893980. I have two model projects available — one contrived, the other using my actual SwiftData models.
Now the Details
I am developing a SwiftUI/SwiftData app. I am (currently) using Xcode 26.5-beta-3.
I set up an alpha-test build using the following approach:
public class DatabaseSchema {
public let dbSchema: Schema = Schema([
Model1.self, ... , Model16.self
], version: Schema.Version(0, 9, 0))
public var modelContainer: ModelContainer {
let container: ModelContainer
let modelConfiguration = ModelConfiguration(schema: dbSchema,
isStoredInMemoryOnly: false)
do {
container = try ModelContainer(for: dbSchema,
migrationPlan: nil,
configurations: [modelConfiguration])
} catch {
fatalError("Failed to creae model conainer")
}
return container
}
This defines database version 0.9.
For version 1.0, I made three changes to the database:
- added an attribute of type
Stringto Model2. - added three attributes of type
[Struct], whereStructconforms toCodable,EquatableandHashableto Model3, and - added a new model (which I'll call Model17)
I define two schemas:
public enum Schema090: VersionedSchema {
public static var versionIdentifier = Schema.Version(0, 9, 0)
public static var models: [any PersistentModel.Type] = [
Model1.self, Schema090.Model2.self,
Schema090.Model3.self, ... ]
}
and
public enum Schema100: VersionedSchema {
public static var versionIdentifier = Schema.Version(1, 0, 0)
public static var models: [any PersistentModel.Type] = [
Model1.swift, Schema100.Model2.self,
Schema100.Model3.self, ..., Model16.self,
Schema100.Model17.self ]
}
For models that changed, I use the following approach:
public typealias Model3 = Schema100.Model3
extension Schema090 {
@Model final class Model3 {
...
}
public init() {
...
}
}
extension Schema100 {
@Model final class Model3 {
...
<added attributes, initialized>
}
public init() {
...
}
}
The DatabaseSchema class was modified as follows:
public class DatabaseSchema {
public let dbSchema: Schema = Schema([
Model1.self, Schema100.Model2.self, Schema100.Model3.self,
... , Model16.self, Schema100.Model17.self
], version: Schema.Version(1, 0, 0))
public var modelContainer: ModelContainer {
let container: ModelContainer
let modelConfiguration = ModelConfiguration(schema: dbSchema,
isStoredInMemoryOnly: false)
do {
container = try ModelContainer(for: dbSchema,
migrationPlan: MigrationPlan.self,
configurations: [modelConfiguration])
} catch {
fatalError("Failed to creae model conainer")
}
return container
}
where the migration plan is the trivial custom migration that makes sure that all added attributes of existing records are properly initialized.
enum MigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] = [
Schema090.self, Schema100.self ]
static var stages: [MigrationStage] = [version090ToVersion100]
static let version090ToVersion100 =
MigrationStage(fromVersion: Schema090.self,
toVersion: Schema100.self, willMigrate: { _ in },
didMigrate: { context in
let models = try context.fetch(
FetchDescriptor<Schema100.Model3>())
for model in models {
< initial the added attributes >
{
try context.save()
})
}
This is all simple stuff. Nothing particularly fancy here. But running this code always crashes in the ModelContainer initializer. In my two sample projects, I get two different error messages —
- in the contrived example, the error message is
Code=134110 "An error occurred during persistent store migration."
reason=Cannot migrate store in-place: Validation error missing
attribute values on mandatory destination attribute, ...
and in the sample project that uses my actual data model, I get
NSCocoaErrorDomain Code=134504 "Cannot use staged
migration with an unknown model version."
My Thoughts
Since obviously most folks are doing SwiftData migrations without the problems I am experiencing, the obvious possibilities are
- I'm doing something stupid that I just don't see.
- There is a problem because the original schema was given a version value of
Schema.Version(0, 9, 0). (i.e., major version number was0) - There is a problem because I am adding an attribute of type
[Struct]whereStructisCodable,Hashable, andEquatable. I.e., migration isn't working properly with attributes which are stored as their codable representations.
Or maybe something else? In any case, any help you can offer would be greatly appreciated.
Thanks for providing the sample app, which does help. With it, I am able to reproduce the issue and figure out what happens there.
The root cause of the issue is that Schema090 and Schema100 share some un-versioned SwiftData models, which are related to models that are different between the schema versions.
Specifically, both Schema090 and Schema100 use Session and Team, which are un-versioned and are related to Cause and Pouch, respectively. And yet, Cause and Pouch are versioned and changed between schema 0.9.0 and 1.0.0, and that seems to confuse SwiftData. Versioning Session and Team by wrapping them with their schema, even they are not changed from 0.9.0 and 1.0.0, fixes the issue.
When defining SwiftData models, I’d always put the models into a schema. This makes the model version clearer, and the schema evolvement easier.
I've tweaked your code in the way described above and sent it back via the DTS channel. You can give it a try and share here if that works on your side.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.