SwiftData - Context missing for optional

I have encountered an issue that when using a ModelActor to sync data in the background, the app will crash if one of the operations is to remove a PersistentModel from the context.

This is running on the latest beta of Xcode 16 with visionOS 1.2 as target and in Swift 6 language mode.

The code is being executed in a ModelActor.

The error is first thrown by: #5 0x00000001c3223280 in PersistentModel.getValue<τ_0_0>(forKey:) ()

Thread 1: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://97AA86BC-475D-4509-9004-D1182ABA1922/Reminder/p303), implementation: SwiftData.PersistentIdentifierImplementation))

func globalSync() async {
        
        await fetchAndSyncFolders()
        
        let result = await fetchReminders()
        switch result {
        case .success(let ekReminders):
            var localReminders = (try? await fetch(FetchDescriptor<Reminder>())) ?? []
            
            // Handle local reminders with nil ekReminderID by creating new EKReminders for them
            for reminder in localReminders {
                if reminder.ekReminderID == nil {
                    await self.createEkReminder(reminder: reminder)
                }
            }
            
            // Re-fetch local reminders to include newly created EKReminderIDs
            localReminders = (try? await fetch(FetchDescriptor<Reminder>())) ?? []
            
            var localReminderDict = [String: Reminder]()
            for reminder in localReminders {
                if let ekReminderID = reminder.ekReminderID {
                    if let existingReminder = localReminderDict[ekReminderID] {
                        self.delete(model: existingReminder)
                    } else {
                        localReminderDict[ekReminderID] = reminder
                    }
                }
            }
            
            let ekReminderDict = createReminderLookup(byID: ekReminders)
            
            await self.syncReminders(localReminders: Array(localReminderDict.values), localReminderDict: localReminderDict, ekReminderDict: ekReminderDict)
            
            // Merge duplicates
            await self.mergeDuplicates(localReminders: localReminders)
            
            save()
            
        case .failure(let error):
            print("Failed to fetch reminders: \(error.localizedDescription)")
        }
    }
Answered by DTS Engineer in 797958022

Thread 1: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://97AA86BC-475D-4509-9004-D1182ABA1922/Reminder/p303), implementation: SwiftData.PersistentIdentifierImplementation))

I am pretty sure that simply deleting a model object using (or not) a model actor (ModelActor) doesn't trigger the mentioned crash.

This error indicates that your model object doesn't have a valid model context, which can happen when you hold a SwiftData model object in a SwiftUI view and continue to access the object (as the view is updated) after it was deleted.

If that is not your case, please share a minimal project, with detailed steps, to reproduce the issue. I'll be interested in taking a look.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

same issue here.

I am getting the same problem. Although I am not using a ModelActor to remove my objects, I get the same error when removing an object via a context menu in my SwiftUI view. In theory, calling modelContext.delete should run without any issues; I am inclined to believe this is a bug.

Same issue here. The same code works in iOS 17 but is broken in iOS 18.

Thread 1: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://97AA86BC-475D-4509-9004-D1182ABA1922/Reminder/p303), implementation: SwiftData.PersistentIdentifierImplementation))

I am pretty sure that simply deleting a model object using (or not) a model actor (ModelActor) doesn't trigger the mentioned crash.

This error indicates that your model object doesn't have a valid model context, which can happen when you hold a SwiftData model object in a SwiftUI view and continue to access the object (as the view is updated) after it was deleted.

If that is not your case, please share a minimal project, with detailed steps, to reproduce the issue. I'll be interested in taking a look.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

I was running into this error when trying to delete an object from SwiftData when using an actual device on iOS 18 beta but not on a simulator running iOS 17.

My model did have a @Relationship property attached to it as well.

I added the following code when inserting an object and haven't gotten this crash the 10+ times I tried. Not idea if it's just a random coincidence or a work around for some bug.

 do {
    try modelContext.save()
 } catch {
    print(error)
 }

I'm also getting this crash as well on iOS18 simulators in Xcode 16 b4 but not on iOS17 simulators, it looks related to deleting a object from within a context menu I've opened up a feedback with the attached project FB14672741

I'm having the same issue. Things I tried (none of them worked):

  • Remove .cascade delete rule
  • Remove all children-type entities before removing the parent-type entity
  • .swipeActions as well as .onDelete

I also tried changing the method of deletion to the following. This tries to delete entity Object that has a to-many relationship children: [Child].

    guard let id = object.id else {
      return
    }
    do {
      try container.mainContext.delete(model: Object.self, where: #Predicate { object in
        object.id == id
      })
    } catch {
        print(error)
    }

This does not crash the app, but fails to delete the entity with the following console output:

Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={Reason=Entity named:Object not found for relationship named:children, MissingEntity=Object. (<NSEntityDescription: 0x6000035100b0>) ...

I'm not sure what this means, perhaps someone more clever will find it useful. @DTS Engineer

Im having the same issue..I delete an object in ios 18 on my physical device it crashes with :

SwiftData/BackingData.swift:251: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://92F8A7FF-1C0A-4099-8654-BCE97E36325D/ExerciseSession/p19), implementation: SwiftData.PersistentIdentifierImplementation))

when I test the same thing on ios17 in a simulator and physical divice it works perfectly fine. Im inclined to agree that this is a swiftData bug in ios18

I was stuck on this too. Turns out I needed to update my @Relationship to accurately describe what was happening. For example, when I deleted an item I would get this crash until I added a deleteRule in my relationship.

Anytime ive gotten SwiftData crashes that were hard to debug, it's always been the @Relationship so far

Hello all, I'm facing the same issue - works fine on iOS 17. Crash on iOS 18 beta 5 (iOS and Xcode). Happens on device and simulator (tested on these platforms - iPhone, iPad, watchOS)

I have the following SwiftData structure. CloudKit configuration - Room Session

ModelContext activity is handled on SwiftUI view (create model, insert, save)

Room has cascade array of Session.

Initial state: No sessions. Create new session and append it to room's sessions. Delete the session. I check the state now - room is exist with empty sessions, as expected Create a new one. Crash on -

        _$observationRegistrar.access(self, keyPath: \.room)
        return self.getValue(forKey: \.room)
    }

I print the PersistentIdentifier before the crash and everything seems to be ok -


PersistentIdentifier(id: CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:]: <NSCloudKitMirroringDelegate: 0x303ab00f0>: Observed context save: <NSPersistentStoreCoordinator: 0x302ea1ce0> - <NSManagedObjectContext: 0x303ea5110>

SwiftData.PersistentIdentifier.ID(url: x-coredata://ED065B2F-2704-46AD-88E1-4F1BE2BA7098/Session/p44), implementation: CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitExporter analyzeHistoryInStore:withManagedObjectContext:error:]: <PFCloudKitExporter: 0x302598370>: Exporting changes since (0): <NSPersistentHistoryToken - {

SwiftData.PersistentIdentifierImplementation) SwiftData.PersistentModel.persistentModelID.getter : SwiftData.PersistentIdentifier

PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://ED065B2F-2704-46AD-88E1-4F1BE2BA7098/Room/p8), implementation: SwiftData.PersistentIdentifierImplementation)

PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://ED065B2F-2704-46AD-88E1-4F1BE2BA7098/Room/p8), implementation: SwiftData.PersistentIdentifierImplementation)


After the crash I open my app again, the session appears and everything works as expected.

Hope this helps.

Thanks a lot, Dudi

Is there an update on this? I still haven't found a fix.

This is still an issue for me on the XCode RC. Unsure of what to even look for to debug. Anybody else find a fix or any temporary workarounds? 

I kind of missed the replies and comments here because the Safari notifications didn't quite work for me :-(. Now I am picking up thanks to folks who reached out me directly.

What is the recommended way of handling the situation if a SwiftUI View is holding a reference to the Model but the model gets deleted?

I typically consider the following patterns:

  1. Avoid deleting an object in the view that accesses the information of the object. If I have a list view that lists some objects and a detail view to show the details of the selected object, I'd put the delete feature in the list view (so users can swipe to delete), and not in the detail view. That way, when an object is deleted, there is no way to go into the detail view that uses the object.

  2. For views that need to hold an object that can potentially be deleted externally, make the object an optional, and nullify it when I do the deletion.

If you delete an object and save the deletion, but see that the object still exists in a relationship of the other object, meaning that the delete rule doesn't work, I'd suggest that you file a feedback report with a reproducible case, and share the report ID here.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Also getting this error in Xcode RC 16. It seems happen whenever I call save after a delete.

modelContext.delete(transaction)
try? modelContext.save()

It does not seem to matter if the delete comes from within a component or from a ForEach.onDelete it yields the same error.

SwiftData/BackingData.swift:251: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://13C3453D-78A0-423B-841D-FF28F6EB2B24/Transaction/p998), implementation: SwiftData.PersistentIdentifierImplementation))

I am also experiencing the same issue.

It works fine on the actual iPhone after updating to iOS 18, but when deleting in the Mac Catalyst app and calling try ctx.save(), the app crashes with the error 'SwiftData/BackingData.swift:251: Fatal error: Context is missing for Optional.'

Thank you for your hard work! 👍

@DTS Engineer

Hi, do you have an update on this please? I'm getting crashes from sessions in production from customers on iOS 18.0. This appears to still be happening Beta 5 of iOS 18.1. Let me know if I can provide more information beyond what others have shared in the thread. Thank you so much!

I'm seeing the same crash after updating iPhone to iOS18. It doesn't crash the sim, which is iOS17 for me. Also a very weird thing is that if I don't call saveContext() is don't crash (but the context does seem to update and look like the record is deleted??). Thankfully I haven't released app to prod yet. This is quite worrying. I've spent a lot time trying different way of passing in a context. This doesn't happen on iOS 17.

this seem to work in my delete function, but shouldn't I have to save the context? container.mainContext.delete(recording) // saveContext()

SwiftData/BackingData.swift:251: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://2B4AE978-7D52-4789-A52A-4593CEBF5690/Recording/p27), implementation: SwiftData.PersistentIdentifierImplementation))

Nevermind... sorry. not saving the context means that on reload the record hasn't actually been deleted. I guess this is now a launch blocker as crashing every time something is deleted is extremely bad. :^(

I have found a solution, at least one that works for my project. I hope it can help others here!

The issue wasn't in the code I had to delete the record from the model context. The problem was an improper use of Binding.

A parent view was presenting a list of child views. Into that child view I was passing a "Recording". Within the child that Recording was an at Binding. That was totally unnecessary and I think causes a conflict with the model context being used by the child(?). So it was being passed in as a constant like this:

                    List {
                        ForEach(filteredRecordings) { recording in
                            RecordingItemView(
                                recording: .constant(recording), 

Removing the Binding and changing a regular property fixed my iOS18 crash:

List { ForEach(filteredRecordings) { recording in RecordingItemView( recording: recording,

The UI of my parent view is already being updated via changes to the modelContext... so the Binding is just a total mistake.

Good luck!

hey I can confirm it happens when calling save after delete. Doing the context save after a short delay seems to work for now


Button {
    modelContext.delete(occurrence)
    dismiss()
    Task {
        try? await Task.sleep(nanoseconds: 1_000_000_000)
        do {
            try modelContext.save()
        } catch {
            print(error.localizedDescription)
        }
    }
} label: { 
    Text("Delete Occurence") 
}

This error indicates that your model object doesn't have a valid model context, which can happen when you hold a SwiftData model object in a SwiftUI view and continue to access the object (as the view is updated) after it was deleted.

In my case it was exactly as @DTS Engineer pointed out. One of my parent views State properties was holding a model object where the relationship property was a deleted model object. That relationship was still accessed in the parent view and lead to the crash. Explicitly setting those states to nil helped resolving the issue.

It took some time to identify where the issue happened exactly. What helped was the backtrace of the main thread inside the Debug Navigator. Hope that helps.

I have had similar problems when moving to macOS 15 (for a Mac app). The issues seem to have been resolved in macOS 15.1 beta 5.

Hi everyone! Stumbled upon the same issue recently. When trying to delete an object from its DetailsPage - getting a crash "Fatal error: Context is missing for"

It seems to be very much related to what properties of the object are being used on the View that suppose to disappear after deletion. DetailsPage in my case, but it can be a ListItemView just as well.

What I figured, that there are 3 things that together lead to this crash:

  1. The View that "holds" the object must use some of the object's relationship(s) propertiers. For example, count of children objects, or the name of the parent object, etc.
  2. There must be try context.save() after deletion of model object.
  3. It must be iOS 18. Yes, this behavior is new. More on that later.

Test setup

Is quite simple. You can download SampleTrips SwiftData app from AppleDeveloper

Navigate to BucketListView.swift and modify a little a struct BucketListItemToggle so that it displays some of the item's parent values.

In order to see the crash in action easier, I'd also suggest to make bucket-list-item deletion upon button press (not swipe action).

With swipe-action, crash is also reproducible - just add try? modelContext.save() to deleteItems(at:). The crash will happen not exactly after deletion, but after subsequent addition of new bucket-list-item. This is probably related to the way how swipeAction removes the view from hierarchy.

Run on iOS18 device OR simulator. Create a Trip, go to Trip details > View Bucket List > Create a BucketListItem (feel free to create several) > Press on any item. Observe the crash.

Note: with this demo project setup, crash happens in about 80% cases when deleting an item. Suspicion is that the more "relational-properties" the child view consumes - the higher chance for a crash.

PS: I've also added Text("\(item.persistentModelID)") to the item row, just to see that the crash indeed happens because of the view being deleted.

Explanation (at least an attempt)

As you can see, crash happens upon trying to access trip? property of the item. This is a "relational" (parent) property of the BucketListItem model.

👉 Seems like iOS18 started to be more strict when accessing parent/children properties when the object itself was removed from the context.

Indeed, if we do po item.modelContext in that breakpoint - we will see that it is nil. In previous iOS versions, it would just fallback and return nil when asking for such trip? property. But on iOS18 - it seems to try to unfault a relation, sees that context is missing and throws a fatal error...

Now, to the question why the view which should disappear is trying to refresh? Here is just my assumption based on observation of Self._printChanges(). Basically that is how SwiftUI always worked. For one reason or another, it recognized a change and needed to refresh the view before parent view recognized that this view should no longer exist in the first place...

Possible solutions

There are some options that I guess one can try:

  1. Consider removing context.save(). If you have a context with autosaveEnabled -- forcing it to save might not be necessary. This seems to give SwiftUI some time to refresh the "view-being-deleted" without an issue. Then parent view will recognise the change and remove the child view completely as expected.
  2. Don't use "relational-properties" in child views. This is much easier said than done. You can pass all relevant values "from above" and make you child views as discrete as possible.
  3. Add if object.modelContext == nil { EmptyView() } else { ... } in bodies of your views which object can get removed.
  4. Simulate fallback to pre-iOS18 by writing safe getters and use them in views to read data from relationships. E.g. var safeTrip: Trip? { guard modelContext != nil else { return nil }; return trip }

For my project, I was lucky with being able to use option 1. But I'm considering adding safe getters anyway just in case 🫣

Would be awesome to hear from Apple if our observations are correct or not 🤞

Thank you all & have fun coding 🙂

My solution to this so far was listening to onDisappear method of an item in the ForEach and calling try? modelContext.save() manually. Autosave is not disabled and everything else works as default config.

Hope this helps :)


// Parent view
ForEach(items) { item in
    ItemsGrid(item: item)
        .onTapGesture {
            markAsCompleted(item)
         }
         .modelContext(modelContext)
         .onDisappear {
              if (item.isDeleted) {
                  print("Item deleted: \(item.isDeleted)")
                       try? modelContext.save()
                   }    
               }
          }



// In Item Detail View: 
// I'm only calling this to trigger onDisappear method
private func deleteItem() {
    modelContext.delete(habit)
}
SwiftData - Context missing for optional
 
 
Q