SwiftData Relationship Delete Not Working (SwiftData/PersistentModel.swift:359)

SwiftData delete isn't working, when I attempt to delete a model, my app crashes and I get the following error:

SwiftData/PersistentModel.swift:359: Fatal error: Cannot remove My_App.Model2 from relationship Relationship - name: model2, options: [], valueType: Model2, destination: Model2, inverseName: models3, inverseKeypath: Optional(\Model2.models3) on My_App.Model3 because an appropriate default value is not configured.

I get that it's saying I don't have a default value, but why do I need one? Isn't @Relationship .cascade automatically deleting the associated models?

And onto of that, why is the error occurring within the do block, shouldn't it be caught by the catch, and printed?

I have put together a sample project below.

import SwiftUI
import SwiftData

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(for: Model3.self)
        }
    }
}

@Model
class Model1 {
    var name: String
    @Relationship(deleteRule: .cascade, inverse: \Model2.model1) var models2: [Model2] = []
    init(name: String) {
        self.name = name
    }
}

@Model
class Model2 {
    var name: String
    var model1: Model1
    @Relationship(deleteRule: .cascade, inverse: \Model3.model2) var models3: [Model3] = []
    init(name: String, model1: Model1) {
        self.name = name
        self.model1 = model1
    }
}

@Model
class Model3 {
    var name: String
    var model2: Model2
    init(name: String, model2: Model2) {
        self.name = name
        self.model2 = model2
    }
}


struct ContentView: View {
    @Query var models1: [Model1]
    @Environment(\.modelContext) var modelContext
    var body: some View {
        NavigationStack {
            List(models1) { model1 in
                Text(model1.name)
                    .swipeActions {
                        Button("Delete", systemImage: "trash", role: .destructive) {
                            modelContext.delete(model1)
                            do {
                                try modelContext.save()
                                //SwiftData/PersistentModel.swift:359: Fatal error: Cannot remove My_App.Model2 from relationship Relationship - name: model2, options: [], valueType: Model2, destination: Model2, inverseName: models3, inverseKeypath: Optional(\Model2.models3) on My_App.Model3 because an appropriate default value is not configured.
                            } catch {
                                print(error.localizedDescription)
                            }
                        }
                    }
            }
            .toolbar {
                Button("Insert", systemImage: "plus") {
                    modelContext.insert(Model3(name: "model3", model2: Model2(name: "model2", model1: Model1(name: "model1"))))
                }
            }
        }
    }
}
Answered by DTS Engineer in 822395022

The issue should go away if you make the to-one relationships optional:

@Model
class Model2 {
    var name: String
    var model1: Model1?
    ...
}

@Model
class Model3 {
    var name: String
    var model2: Model2?
    ...
}

To be clear, I understand that your intent is to express a non-optional to-one relationship with Swift, and yet it is a caveat that, when using SwiftData one-to-many relationship + cascade delete rule, you would want to make the to-one relationship optional.

If using non-optional to-one relationship doesn't work for you, I'd suggest that you file a feedback report and share your report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Accepted Answer

The issue should go away if you make the to-one relationships optional:

@Model
class Model2 {
    var name: String
    var model1: Model1?
    ...
}

@Model
class Model3 {
    var name: String
    var model2: Model2?
    ...
}

To be clear, I understand that your intent is to express a non-optional to-one relationship with Swift, and yet it is a caveat that, when using SwiftData one-to-many relationship + cascade delete rule, you would want to make the to-one relationship optional.

If using non-optional to-one relationship doesn't work for you, I'd suggest that you file a feedback report and share your report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

SwiftData Relationship Delete Not Working (SwiftData/PersistentModel.swift:359)
 
 
Q