How to safely apply SortDescriptor(\.sortOrder) with Swift 6 Concurrency and @Model

Hi all,

I’m working on a SwiftUI app using SwiftData and recently enabled Swift 6 in my project. After doing so, I started getting the following error when using a SortDescriptor with a key path:

Type 'ReferenceWritableKeyPath<ServerDomain, Int>' does not conform to the 'Sendable' protocol

This happens in a SwiftData @Query like this:

@Query(sort: [SortDescriptor(\ServerDomain.sortOrder)])
private var servers: [ServerDomain]

Here’s a simplified version of my model:

@Model
class ServerDomain {
    var id: UUID
    var name: String
    var sortOrder: Int

    init(id: UUID = .init(), name: String, sortOrder: Int) {
        self.id = id
        self.name = name
        self.sortOrder = sortOrder
    }
}

It seems that since ReferenceWritableKeyPath is not Sendable by default, Swift 6’s stricter concurrency model now flags this as an error. I understand I can suppress the error using @unchecked Sendable, but I’d like to follow concurrency safety best practices if possible.

My question is:

How can I safely apply SortDescriptor with SwiftData models and Swift Concurrency in Swift 6, without violating Sendable constraints?

Is there a recommended approach for using key paths like this inside Swift concurrency-compatible contexts?

Thanks!

You should be able to tell the compiler your KeyPath instance is Sendable. You might also need to confirm the Root and Value are also Sendable.

Thanks for the suggestion!

I tried marking my model as @unchecked Sendable, like this:

@Model
final class ServerDomain: @unchecked Sendable {
    var id: UUID
    var name: String
    var sortOrder: Int

    init(id: UUID = .init(), name: String, sortOrder: Int) {
        self.id = id
        self.name = name
        self.sortOrder = sortOrder
    }
}

However, this doesn’t resolve the issue — I’m still seeing the same compiler error:

Type 'ReferenceWritableKeyPath<ServerDomain, Int>' does not conform to the 'Sendable' protocol

It looks like marking the model class as @unchecked Sendable isn’t enough, since the error seems to be related to the key path itself rather than the model type directly.

If you have an example of how this should be done correctly in a Swift 6 + SwiftData setup — ideally without suppressing the compiler’s Sendable checks I’d really appreciate it.

Thanks again!

Hi, I cannot reproduce the error you saw on my machine.

What version of Xcode are you using? And can you show the complete code where you used @Query?

I’ve uploaded a minimal example project to help demonstrate the issue. You can download it here:

Xcode settings:

  • Version 26.0 beta 2 (17A5241o)
  • Swift 6
  • Approachable concurrency: YES
  • Default actor isolation: Main
  • Swift concurrency checking: Complete

This is the full code from the attached project:

QueryConcurrencySwift6App.swift

import SwiftUI
import SwiftData

@main
struct QueryConcurrencySwift6App: App {
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([
            Item.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 {
            ContentView()
        }
        .modelContainer(sharedModelContainer)
    }
}

Item.swift

import Foundation
import SwiftData

@Model
final class Item {
    var timestamp: Date
    
    init(timestamp: Date) {
        self.timestamp = timestamp
    }
}

ContentView.swift

import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query(sort: [SortDescriptor(\Item.timestamp)]) private var items: [Item]

    var body: some View {
        NavigationSplitView {
            List {
                ForEach(items) { item in
                    NavigationLink {
                        Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
                    } label: {
                        Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
                    }
                }
                .onDelete(perform: deleteItems)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
        } detail: {
            Text("Select an item")
        }
    }

    private func addItem() {
        withAnimation {
            let newItem = Item(timestamp: Date())
            modelContext.insert(newItem)
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(items[index])
            }
        }
    }
}

#Preview {
    ContentView()
        .modelContainer(for: Item.self, inMemory: true)
}

Error:

@Query(sort: [SortDescriptor(\Item.timestamp)]) private var items: [Item]
Type 'ReferenceWritableKeyPath<Item, Date>' does not conform to the 'Sendable' protocol

Ah, there it is. Currently, MainActor-default-isolation does not work well with certain frameworks, these frameworks require some custom types to be nonisolated. You can check the related discussions here and here.

1 Like

Thanks a lot, that really helped clarify things!
For now, I’ll go with the nonisolated workaround as it solves the issue cleanly in my case. Appreciate your help!