iCloud & Data

RSS for tag

Learn how to integrate your app with iCloud and data frameworks for effective data storage

CloudKit Documentation

Posts under iCloud & Data subtopic

Post

Replies

Boosts

Views

Activity

iCloud Drive silent upload deadlock caused by stale HTTP/3 session in nsurlsessiond (FB22476701)
Summary On macOS 26.4.1 (25E253), iCloud Drive file uploads can enter a silent deadlock where every upload attempt fails at the transport layer. No error is surfaced anywhere — not in Finder, not in System Settings, not in the iCloud status panel. The upload queue simply stops. Other iCloud services (Photos, Mail, App Store) continue to work normally through the same networking infrastructure at the same time. Root Cause The issue is a stale HTTP/3 (QUIC) session cached in the user-level nsurlsessiond process's BackgroundConnectionPool. The deadlock cycle: cloudd requests an upload to the GCS storage endpoint nsurlsessiond provides the cached (broken) HTTP/3 session The TLS handshake succeeds, but the body upload dies mid-transfer (err=T, requestDuration=-1.000, responseHeaderBytes=0) cloudd retries with a new connectionUUID — but nsurlsessiond still routes through the same poisoned QUIC session This repeats indefinitely Killing cloudd alone does not help — nsurlsessiond retains the poisoned pool. Only killing both the user-level cloudd and nsurlsessiond clears the pool and forces a fresh protocol negotiation. The Smoking Gun After killing both daemons, the system falls back to HTTP/1.1 for the stuck uploads — and they complete instantly: Before Kill After Kill Protocol h3 (QUIC) http/1.1 (TCP) Largest upload Failed at partial offsets 26 MB in 1.6 seconds Server response 0 bytes 596 bytes (normal) Same endpoint, same files, same network interface (en5), same power state. The only change was the protocol negotiation after a fresh nsurlsessiond. Reproduction Reproduced 3 times on April 11, 2026 using a standardized set of 8 test files (8 bytes to 20 MB) in a non-shared iCloud Drive folder. Each run showed the identical pattern: Small files (<100 KB) squeeze through before the QUIC session stalls Larger files trigger the deadlock every time 5–6 retries with fresh connectionUUIDs, all failing over protocol=h3 After kill cloudd + nsurlsessiond: immediate flush via protocol=http/1.1 An automated evidence-collection script (collect_h3_deadlock_evidence.sh) captures paired before-kill / after-kill logs. Included in the Feedback report. Symptom Check (for others hitting this) /usr/bin/log show --predicate 'process == "cloudd"' --last 5m 2>&1 \ | grep "putContainer.*err=T.*requestDuration=-1.000.*protocol=h3" | wc -l Output > 0 = this deadlock. Output = 0 = different issue. Recovery (one-liner) kill $(ps -axo user,pid,command | awk -v u="$USER" \ '($1==u && /CloudKitDaemon.framework.*cloudd/ && !/--system/) \ || ($1==u && /\/usr\/libexec\/nsurlsessiond/ && !/--privileged/) \ {print $2}') Both daemons respawn within 1–2 seconds. Do not use killall nsurlsessiond — it would also kill the privileged system instance. What was ruled out Network connectivity (Photos uploaded 8 MB through the same pool simultaneously) iCloud account (metadata operations succeeding, only body uploads failing) File type/content (random data, correlation is with size, not type) Storage quota (1.65 TB free) CFNetworkHTTP3Enabled=false (key is ineffective in 26.4.1) Suggested fixes (from the Feedback report) CFNetwork: Invalidate the QUIC session after N consecutive requestDuration=-1.000 failures CloudKit/NSURLSession: Expose a pool invalidation API like [NSURLSession invalidatePoolEntryForEndpoint:] cloudd: Self-healing retry — create a fresh NSURLSession after M consecutive deadlock-signature failures Finder: At minimum, surface the stuck state to the user instead of failing silently Filed as FB22476701 — includes full reproduction timelines, request/connection UUIDs, sysdiagnose, and a 12-page investigation PDF with architecture diagrams and protocol comparison tables. If you're experiencing the same issue, please file a duplicate referencing FB22476701 — Apple prioritizes by duplicate count. System MacBook Air, macOS 26.4.1 (25E253) iCloud Drive with Desktop & Documents sync en0 (WLAN) + en5 (USB-LAN via Studio Display)
7
0
289
1d
Sandboxed app loses iCloud Drive access mid-session on macOS 26 — kernel refuses sandbox extension, FP client rejected (NSFileProviderErrorDomain -2001)
Starting somewhere around macOS 26.3, my sandboxed file manager spontaneously loses access to ~/Library/Mobile Documents mid-session. Setup: at launch, the user grants access to '/', '/Users', or '~' via NSOpenPanel; I store a security-scoped bookmark and call startAccessingSecurityScopedResource(). This works fine - including iCloud Drive - until some point mid-session. When it breaks, two things happen simultaneously: Enumeration fails: NSCocoaErrorDomain Code=257 (NSFileReadNoPermissionError)< NSPOSIXErrorDomain Code=1 (EPERM) Console shows the kernel refusing extension issuance: couldn't issue sandbox extension com.apple.app-sandbox.read for '/Users//Library/Mobile Documents': Operation not permitted And probing NSFileProviderManager confirms the process has been rejected system-wide: NSFileProviderManager.getDomainsWithCompletionHandler > NSFileProviderErrorDomain Code=-2001 "The application cannot be used right now." (underlying Code=-2014) What makes this specific to FP-backed paths: regular paths under the same '/' bookmark (~/Library/Application Support, etc.) stay accessible and recover normally with a fresh startAccessingSecurityScopedResource() call. Only ~/Library/Mobile Documents and its subtree fail - the entire tree, including the parent directory itself. Relaunch always restores access. What I've tried and ruled out: Re-resolving the bookmark + startAccessingSecurityScopedResource() - returns stale=false, granted=true but access is not restored; the kernel still refuses extension issuance for FP-traversing paths. NSFileCoordinator coordinated read - doesn't help; the coordinator depends on the same sandbox extension the kernel is refusing. Instantiating NSFileProviderManager(for: domain) per domain - fails with -2001 for every domain, confirming the rejection is process-wide, not path- or domain-specific. My working theory: when a FileProvider daemon (bird/cloudd/fileproviderd) restarts mid-session, the process's FP-client XPC registration is invalidated, and the kernel subsequently refuses to issue sandbox extensions for any path served by FP - even with a valid bookmark. The process seems to have no API path to re-register its FP-client identity without relaunching. Current workaround: I detect the -2001 response and prompt the user to relaunch, then do a programmatic self-relaunch if they confirm (which is obviously horribly intrusive). Questions: Is there an API that lets a sandboxed consumer app reconnect its FP-client identity mid-session, short of relaunching? Is there an entitlement or capability that would make the kernel's extension issuance resilient to FP daemon restarts? Has anyone else hit this on 26.x and found a workaround? Filed as FB22547671.
3
0
88
1d
CloudKit private database operations fail with CKError 15 / HTTP 500 for one container across multiple apps (FB22539748)
We are seeing a CloudKit private database failure for this specific container: iCloud.com.matrixqlc.photodiet.sync Failure pattern: accountStatus succeeds in some cases ensure/create custom zone succeeds but record/database-level operations consistently fail with: CKErrorDomain code = 15 CKInternalErrorDomain code = 2000 HTTP 500 Failing operations include: allRecordZones() databaseChanges(since:nil) allSubscriptions() fetch record zone metadata save record fetch record query records What makes this unusual is that the issue follows the container, not the app. On the same physical device, same Apple ID, same developer team: PhotoDiet + iCloud.com.matrixqlc.photodiet.sync => fails RepaymentCalculator + iCloud.com.matrixqlc.photodiet.sync => fails PhotoDiet + iCloud.com.matrixqlc.repaymentcalculator.sync2 => succeeds RepaymentCalculator + iCloud.com.matrixqlc.repaymentcalculator.sync2 => succeeds So this does not currently look like: app-specific entitlement/provisioning issues device/account issues CloudKit API misuse in one app record schema or app business logic issues It currently looks like the container iCloud.com.matrixqlc.photodiet.sync itself may be in a bad backend state. Sample request identifiers: RequestUUID: C8403047-0037-4D36-A7A7-CF3C83584A42 RequestUUID: 04437D9D-115E-45F5-87B5-A8CD146AE705 RequestUUID: C924B620-BAEE-403D-B944-151ADCF3419F RequestUUID: A54E79E1-6037-4533-BA09-18FBC436851C RequestUUID: 3EFD8913-3781-47CF-A48C-B651BF38EA50 RequestUUID: 2677A991-40B3-42AB-9CE5-3C4F1288EE08 Feedback Assistant ID: FB22539748 Has anyone seen a container-specific CloudKit private database failure like this, where multiple apps under the same team can access one container normally but consistently fail on another container with CKError 15 / HTTP 500?
1
0
47
3d
SwiftData document-based app crashes on undo/redo without ModelContext.transaction(block:)
Overview I'm developing a document-based app for macOS using SwiftData. When I undo/redo changes using Command-Z/Command-Shift-Z, the app reliably crashes with the following error: SwiftData/ModelSnapshot.swift:46: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<DocumentTest.ChildItem> And before the app crashes, what always happens is that UndoManager stops removing/restoring instances of ChildItem (but continues to remove/restore instances of ParentItem). The issue goes away when I enclose the relevant code in ModelContext.transaction(block:). However, this shouldn't be necessary, as ModelContext.autosaveEnabled is true by default. The issues are occurring with Xcode 26.4 (17E192) and macOS Tahoe 26.4 (25E246). I have modified the macOS Document App project template to showcase the issue. The sample project, along with a screen recording of the crash, can be downloaded from here: https://drive.google.com/drive/folders/13bCB1qRZ6273BI81zW2zUUBraSvv6p5w?usp=share_link Is this expected behavior or should I file a bug report in Feedback Assistant? Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file linked above. Open the extracted "DocumentTest" project in Xcode. Build and run the "DocumentTest" app. In the document selection window, click "New Document" at the bottom-left. In the app, click the "+" button at the top-right to add a ParentItem with ChildItems. Click on the added ParentItem's button to add another ChildItem to it. Repeat steps 5–6 until you have 5 ParentItems with an additional ChildItem. Press Command-Z 10 times to undo all the changes. Press Command-Shift-Z 10 times to redo all the changes. Repeat steps 8–9 until UndoManager stops removing/restoring the additional ChildItem, and continue repeating them until the app eventually crashes (you may have to repeat them 5–10 times before the issue occurs). If you uncomment the ModelContext.transaction(block:) at line 13 of ContentView.swift and repeat the same steps above, no ChildItems will go missing and the app will not crash. Code ParentItem Model @Model final class ParentItem { var timestamp: Date @Relationship( deleteRule: .cascade, inverse: \ChildItem.parentItem ) var childItems: [ChildItem] = [] init(timestamp: Date) { self.timestamp = timestamp } } ChildItem Model @Model final class ChildItem { var index: Int var parentItem: ParentItem? init(index: Int) { self.index = index } } Creating, Inserting, and Linking ParentItem and ChildItem // Create and insert ParentItem let newParentItem = ParentItem( timestamp: Date() ) modelContext.insert(newParentItem) // Create and insert ChildItems var newChildItems: [ChildItem] = [] for index in 0..<Int.random(in: 2...8) { let newChildItem = ChildItem(index: index) newChildItems.append(newChildItem) modelContext.insert(newChildItem) } /* Establish relationship between ParentItem and ChildItems */ for newChildItem in newChildItems { newParentItem.childItems.append( newChildItem ) newChildItem.parentItem = newParentItem } Adding an Additional ChildItem to ParentItem // Uncommenting this block fixes the crash // try! modelContext.transaction { // Create and insert the new ChildItem let newChildItem = ChildItem( index: parentItem.childItems.count ) modelContext.insert(newChildItem) // Establish relationship to parentItem parentItem.childItems.append(newChildItem) newChildItem.parentItem = parentItem // }
3
0
238
5d
CKRecordZone deleted when second user accepts zone-wide CKShare
I'm seeing a critical issue where a custom CKRecordZone is consistently deleted server-side when a second iCloud account interacts with a zone-wide CKShare. I've reproduced this 20+ times across two days and have exhausted every client-side fix I can think of. Looking for guidance on what might be going wrong. Setup Container: iCloud.com.cohencooks (production app on App Store) Custom CKRecordZone in owner's private database Zone-wide CKShare(recordZoneID:) (iOS 15+ zone sharing) SwiftData with ModelConfiguration(cloudKitDatabase: .none) — no automatic CloudKit mirroring Acceptance via CKFetchShareMetadataOperation → CKContainer.accept(metadata) (no UICloudSharingController) Minimal reproduction // 1. Owner creates zone + share let zone = CKRecordZone(zoneName: "MyZone") try await privateDB.save(zone) let share = CKShare(recordZoneID: zone.zoneID) share[CKShare.SystemFieldKey.title] = "My Share" as CKRecordValue share.publicPermission = .readWrite let (results, _) = try await privateDB.modifyRecords(saving: [share], deleting: []) // 2. Owner pushes ~500 records to zone — all succeed // 3. Second user (different iCloud account) accepts share let metadata = try await container.shareMetadata(for: shareURL) try await container.accept(metadata) // 4. Owner's next CKFetchRecordZoneChangesOperation → zoneNotFound (code 26) // Zone is permanently gone. allRecordZones() confirms deletion. What I observe Three distinct failure patterns depending on configuration: Pattern 1 — publicPermission = .readWrite, no addParticipant: Zone dies instantly after acceptance. First push notification shows cloudkit.share changed (zone alive), second push notification returns zoneNotFound. The non-owner never successfully wrote anything. Pattern 2 — publicPermission = .none with explicit addParticipant: Zone survives acceptance and 2-3 minutes of bidirectional sync (non-owner pulls 578 records, pushes meal plans back). Then a push notification arrives and the zone is gone. This is dramatically better than Pattern 1 but still fails. Pattern 3 — Container destabilization after repeated testing: After 20+ create/delete cycles in one day, zones die from the owner's own push notifications — no second device involved at all. The container appears to enter an unstable state. What I've ruled out Hypothesis Test Result publicPermission = .readWrite Changed to .none + explicit addParticipant Zone survived longer but still eventually deleted Zone name tombstoning Tested 6 fresh names never used in this container All eventually deleted Non-owner writes causing deletion Gated ALL non-owner push methods (recipe, meal plan, grocery, photo, event) Zone still deleted database.save(share) vs modifyRecords Switched to modifyRecords(saving:deleting:) Zone still deleted NSPersistentCloudKitContainer interference Removed all Core Data CloudKit code Zone still deleted Double share acceptance Fresh app install, single acceptance only Zone still deleted Advanced Data Protection Neither account has ADP enabled Not the cause Programmatic vs system acceptance Tested both container.accept() and tapping share link Zone still deleted CloudKit Dashboard No ZoneDelete operation is visible in the logs. All operations are ZoneFetch, ZoneChanges, RecordQuery, RecordFetch. I do see EphemeralGroup operations targeting the custom zone — not sure what generates those. Comparison with working apps I compared my implementation with another app (Spotbook) that uses the exact same zone-wide CKShare(recordZoneID:) pattern with publicPermission = .readWrite and programmatic acceptance — and it works. The main difference is that app uses CKSyncEngine (iOS 17+) rather than raw CKFetchRecordZoneChangesOperation / CKModifyRecordsOperation. Could CKSyncEngine be handling something internally that prevents this issue? Questions Is there a known interaction between zone-wide CKShare(recordZoneID:) acceptance and zone lifecycle that could cause zone deletion? Does CKSyncEngine handle zone-wide sharing differently than manual CKFetchRecordZoneChangesOperation + CKModifyRecordsOperation? What generates EphemeralGroup operations in CloudKit Dashboard? Could these trigger a zone delete? After 20+ zone create/delete cycles in a container, is there a server-side rate limit or tombstone mechanism that would destabilize new zones? Is the custom programmatic acceptance flow (CKFetchShareMetadataOperation → container.accept()) fully supported for zone-wide shares, or does it require UICloudSharingController? Any guidance would be greatly appreciated. This is blocking multi-user functionality for our app (mesa, a meal planning app on the App Store). Single-user sync works perfectly — the issue only manifests when a second iCloud account is involved. Environment: iOS 18.4.1, Xcode 16+, Swift, SwiftUI
3
0
105
6d
CKRecordZone deleted when second user accepts zone-wide CKShare
I'm seeing a critical issue where a custom CKRecordZone is consistently deleted server-side when a second iCloud account interacts with a zone-wide CKShare. I've reproduced this 20+ times across two days and have exhausted every client-side fix I can think of. Looking for guidance on what might be going wrong. Setup Container: iCloud.com.cohencooks (production app on App Store) Custom CKRecordZone in owner's private database Zone-wide CKShare(recordZoneID:) (iOS 15+ zone sharing) SwiftData with ModelConfiguration(cloudKitDatabase: .none) — no automatic CloudKit mirroring Acceptance via CKFetchShareMetadataOperation → CKContainer.accept(metadata) (no UICloudSharingController) Minimal reproduction // 1. Owner creates zone + share let zone = CKRecordZone(zoneName: "MyZone") try await privateDB.save(zone) let share = CKShare(recordZoneID: zone.zoneID) share[CKShare.SystemFieldKey.title] = "My Share" as CKRecordValue share.publicPermission = .readWrite let (results, _) = try await privateDB.modifyRecords(saving: [share], deleting: []) // 2. Owner pushes ~500 records to zone — all succeed // 3. Second user (different iCloud account) accepts share let metadata = try await container.shareMetadata(for: shareURL) try await container.accept(metadata) // 4. Owner's next CKFetchRecordZoneChangesOperation → zoneNotFound (code 26) // Zone is permanently gone. allRecordZones() confirms deletion. What I observe Three distinct failure patterns depending on configuration: Pattern 1 — publicPermission = .readWrite, no addParticipant: Zone dies instantly after acceptance. First push notification shows cloudkit.share changed (zone alive), second push notification returns zoneNotFound. The non-owner never successfully wrote anything. Pattern 2 — publicPermission = .none with explicit addParticipant: Zone survives acceptance and 2-3 minutes of bidirectional sync (non-owner pulls 578 records, pushes meal plans back). Then a push notification arrives and the zone is gone. This is dramatically better than Pattern 1 but still fails. Pattern 3 — Container destabilization after repeated testing: After 20+ create/delete cycles in one day, zones die from the owner's own push notifications — no second device involved at all. The container appears to enter an unstable state. Inconsistent state after deletion Here's something that might help narrow this down. After one of the zone deletions, I deployed the same build to a second device signed into a different iCloud account that had previously accepted the CKShare. Without sending a new invite, that device found the "Household" zone via allRecordZones() on sharedCloudDatabase — it could pull all 578 records, push updates, and the share URL still resolved. Meanwhile, the owner device (zone creator) gets "zone not found" from both allRecordZones() and direct recordZone(for:) on privateCloudDatabase. So it looks like the zone is deleted from the owner's private database, but the CKShare and zone records remain accessible to participants via the shared database. Participants can still read and write as if nothing happened — the owner just can't see the zone anymore. This also creates a recovery problem — when the owner creates a new zone with the same name, it gets a new CKShare URL, but the participant is still connected to the old "ghost" zone. The two sides are permanently split. Does this mean the zone deletion is happening through a path that doesn't properly clean up the sharing infrastructure? Is this expected behavior when a zone-wide CKShare's zone is deleted, or does it suggest the deletion is happening through an abnormal server-side path? What I've ruled out Hypothesis Test Result publicPermission = .readWrite Changed to .none + explicit addParticipant Zone survived longer but still eventually deleted Zone name tombstoning Tested 6 fresh names never used in this container All eventually deleted Non-owner writes causing deletion Gated ALL non-owner push methods (recipe, meal plan, grocery, photo, event) Zone still deleted database.save(share) vs modifyRecords Switched to modifyRecords(saving:deleting:) Zone still deleted NSPersistentCloudKitContainer interference Removed all Core Data CloudKit code Zone still deleted Double share acceptance Fresh app install, single acceptance only Zone still deleted Advanced Data Protection Neither account has ADP enabled Not the cause Programmatic vs system acceptance Tested both container.accept() and tapping share link Zone still deleted CloudKit Dashboard No ZoneDelete operation is visible in the logs. All operations are ZoneFetch, ZoneChanges, RecordQuery, RecordFetch. I do see EphemeralGroup operations targeting the custom zone — not sure what generates those. Comparison with working apps I compared my implementation with another app that uses the exact same zone-wide CKShare(recordZoneID:) pattern with publicPermission = .readWrite and programmatic acceptance — and it works. The main difference is that app uses CKSyncEngine (iOS 17+) rather than raw CKFetchRecordZoneChangesOperation / CKModifyRecordsOperation. Could CKSyncEngine be handling something internally that prevents this issue? Questions Is there a known interaction between zone-wide CKShare(recordZoneID:) acceptance and zone lifecycle that could cause zone deletion? Does CKSyncEngine handle zone-wide sharing differently than manual CKFetchRecordZoneChangesOperation + CKModifyRecordsOperation? What generates EphemeralGroup operations in CloudKit Dashboard? Could these trigger a zone delete? After 20+ zone create/delete cycles in a container, is there a server-side rate limit or tombstone mechanism that would destabilize new zones? Is the inconsistent state I described (zone gone from owner's private DB but still accessible from participant's shared DB) expected behavior, or does it indicate the deletion is happening through an abnormal path? Is the custom programmatic acceptance flow (CKFetchShareMetadataOperation → container.accept()) fully supported for zone-wide shares, or does it require UICloudSharingController? Any guidance would be greatly appreciated. This is blocking multi-user functionality for our app (mesa, a meal planning app on the App Store). Single-user sync works perfectly — the issue only manifests when a second iCloud account is involved. Environment: iOS 18.4.1, Xcode 16+, Swift, SwiftUI
1
0
85
1w
SwiftData property marked ephemeral getting persisted in CloudKit
Am I misunderstanding the expected behavior here, or is there a bug in the behavior of @Attribute(.ephemeral) tagged SwiftData model properties? The documentation for .ephemeral says "Track changes to this property but do not persist". I started using .ephemeral because @Transient was inhibiting SwiftUI from reacting to changes to the property through @Observable. I am updating the value of my @Attribute(.ephemeral) property about once a second and I am seeing corresponding console log output showing the property as part of the generated CKRecord object. I then confirmed in the CloudKit dev portal that the .ephemeral property was added to the Record schema and contains real values. The behavior seems as though the .ephemeral property is being completely ignored. This is observed in a new Xcode project using SwiftData with CloudKit, Xcode 16.2, macOS 15.3.1 and during Build & Run testing on physical devices.
3
1
843
1w
Does CKSyncEngine have to be re-initialized after an account change event?
According to this comment in the sample project on GitHub and this answer by Apple Staff, CKSyncEngine should be re-initialized after signing out or switching accounts so that "CKSyncEngine schedules a new fetch on init." But according to my tests, CKSyncEngine will schedule a fetch after having a signed out and signed in again, without me ever having to reset the serialized sync state. The documentation doesn't mentioned anywhere that CKSyncEngine should be re-initialized after an account change. In fact, it states that CKSyncEngine will reset its state internally on account changes. So if that's the case, then I'm very confused as to why the "official" recommendation is to re-initialize CKSyncEngine after receiving .signOut or .accountSwitch. Can someone please clarify the correct approach here?
1
0
183
1w
iCloud Sync not working with iPhone, works fine for Mac.
I've been working on an app. It uses iCloud syncing. 48 hours ago everything was working 100%. Make a change on the iPhone it immediately changed on the Mac. Change on the Mac, it immediately changed on the iPhone. I didn't work on it yesterday. I updated to iOS26.4 on the iPhone and 26.4 on the Mac yesterday instead. Today, I pull up the project again. I made NO changes to the code or settings. Make a change on the iPhone it immediately updates on the Mac. Make a change on the Mac, nothing happens on the iPhone. I've waited an hour, and the change never happens. If you leave the iPhone app, then return, it updates as it should. It appears that iCloud's silent notification is to being received by the iPhone. Anyone else having the issue? Is there something new with iOS 26.4 that needs to be adjusted to get this to work? Again, works flawlessly with the Mac, just not with the iPhone.
36
17
8.3k
1w
SwiftData document-based app crashes on undo/redo without ModelContext.transaction(block:)
Overview I'm developing a document-based app for macOS using SwiftData. When I undo/redo changes using Command-Z/Command-Shift-Z, the app reliably crashes with the following error: SwiftData/ModelSnapshot.swift:46: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<DocumentTest.ChildItem> And before the app crashes, what always happens is that UndoManager stops removing/restoring instances of ChildItem (but continues to remove/restore instances of ParentItem). The issue goes away when I enclose the relevant code in ModelContext.transaction(block:). However, this shouldn't be necessary, as ModelContext.autosaveEnabled is true by default. The issues are occurring with Xcode 26.4 (17E192) and macOS Tahoe 26.4 (25E246). I have modified the macOS Document App project template to showcase the issue. The sample project, along with a screen recording of the crash, can be downloaded from here: https://drive.google.com/drive/folders/13bCB1qRZ6273BI81zW2zUUBraSvv6p5w?usp=share_link Is this expected behavior or should I file a bug report in Feedback Assistant? Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file linked above. Open the extracted "DocumentTest" project in Xcode. Build and run the "DocumentTest" app. In the document selection window, click "New Document" at the bottom-left. In the app, click the "+" button at the top-right to add a ParentItem with ChildItems. Click on the added ParentItem's button to add another ChildItem to it. Repeat steps 5–6 until you have 5 ParentItems with an additional ChildItem. Press Command-Z 10 times to undo all the changes. Press Command-Shift-Z 10 times to redo all the changes. Repeat steps 8–9 until UndoManager stops removing/restoring the additional ChildItem, and continue repeating them until the app eventually crashes (you may have to repeat them 5–10 times before the issue occurs). If you uncomment the ModelContext.transaction(block:) at line 13 of ContentView.swift and repeat the same steps above, no ChildItems will go missing and the app will not crash. Code ParentItem Model @Model final class ParentItem { var timestamp: Date @Relationship( deleteRule: .cascade, inverse: \ChildItem.parentItem ) var childItems: [ChildItem] = [] init(timestamp: Date) { self.timestamp = timestamp } } ChildItem Model @Model final class ChildItem { var index: Int var parentItem: ParentItem? init(index: Int) { self.index = index } } Creating, Inserting, and Linking ParentItem and ChildItem // Create and insert ParentItem let newParentItem = ParentItem( timestamp: Date() ) modelContext.insert(newParentItem) // Create and insert ChildItems var newChildItems: [ChildItem] = [] for index in 0..<Int.random(in: 2...8) { let newChildItem = ChildItem(index: index) newChildItems.append(newChildItem) modelContext.insert(newChildItem) } /* Establish relationship between ParentItem and ChildItems */ for newChildItem in newChildItems { newParentItem.childItems.append( newChildItem ) newChildItem.parentItem = newParentItem } Adding an Additional ChildItem to ParentItem // Uncommenting this block fixes the crash // try! modelContext.transaction { // Create and insert the new ChildItem let newChildItem = ChildItem( index: parentItem.childItems.count ) modelContext.insert(newChildItem) // Establish relationship to parentItem parentItem.childItems.append(newChildItem) newChildItem.parentItem = parentItem // }
1
0
137
1w
CKQuerySubscription on public database never triggers APNS push in Production environment
Hi everyone, I have a SwiftUI app using CKQuerySubscription on the public database for social notifications (friend requests, recommendations, etc.). Push notifications work perfectly in the Development environment but never fire in Production (TestFlight). Setup: iOS 26.4, Xcode 26, Swift 6 Container: public database, CKQuerySubscription with .firesOnRecordCreation 5 subscriptions verified via CKDatabase.allSubscriptions() registerForRemoteNotifications() called unconditionally on every launch Valid APNS device token received in didRegisterForRemoteNotificationsWithDeviceToken Push Notifications + Background Modes (Remote notifications) capabilities enabled What works: All 5 subscriptions create successfully in Production Records are saved and queryable (in-app CloudKit fetches return them immediately) APNS production push works — tested via Xcode Push Notifications Console with the same device token, notification appeared instantly Everything works perfectly in the Development environment (subscriptions fire, push arrives) What doesn't work: When a record is created that matches a subscription predicate, no APNS push is ever delivered in Production Tested with records created from the app (device to device) and from CloudKit Dashboard — neither triggers push Tried: fresh subscription IDs, minimal NotificationInfo (just alertBody), stripped shouldSendContentAvailable, created an APNs key, toggled Push capability in Xcode, re-deployed schema from dev to prod Additional finding: One of my record types (CompletionNotification) was returning BAD_REQUEST when creating a subscription in Production, despite working in Development. Re-deploying the development schema to production (which reported "no changes") fixed the subscription creation. This suggests the production environment had inconsistent subscription state for that record type, possibly from the type being auto-created by a record save before formal schema deployment. I suspect a similar issue may be affecting the subscription-to-APNS pipeline for all my record types — the subscriptions exist and predicates match, but the production environment isn't wiring them to APNS delivery. Subscription creation code (simplified): let subscription = CKQuerySubscription( recordType: "FriendRequest", predicate: NSPredicate(format: "receiverID == %@ AND status == %@", userID, "pending"), subscriptionID: "fr-sub-v3", options: [.firesOnRecordCreation] ) let info = CKSubscription.NotificationInfo() info.titleLocalizationKey = "Friend Request" info.alertLocalizationKey = "FRIEND_REQUEST_BODY" info.alertLocalizationArgs = ["senderUsername"] info.soundName = "default" info.shouldBadge = true info.desiredKeys = ["senderUsername", "senderID"] info.category = "FRIEND_REQUEST" subscription.notificationInfo = info try await database.save(subscription) Has anyone encountered this? Is there a way to "reset" the subscription-to-APNS pipeline for a production container? I'd really appreciate any guidance on how to resolve and get my push notifications back to normal. Many thanks, Dimitar - LaterRex
11
1
1.1k
2w
SwiftData document-based app crashes on undo/redo with autosaveEnabled
Overview I'm developing a document-based app for macOS using SwiftData. When I undo/redo changes using Command-Z/ Command-Shift-Z, the app randomly crashes with the following error: SwiftData/BackingData.swift:425: Fatal error: Failed to retrieve the identifier for \ChildItem.parentItem from KnownKeysDictionary:KnownKeysMap: ["parentItem": 2, "isModified": 1, "index": 0] values: [Optional(0), Optional(false), Optional(DocumentTest.ParentItem)] SwiftData._KKMDBackingData<DocumentTest.ChildItem> And sometimes, instead of the app crashing, my created @Model objects simply disappear. They do not reappear in the @Query on undo/redo. Both of these issues go away when I set modelContext.autosaveEnabled = false The issues are occurring with Xcode 26.4 (17E192) and macOS Tahoe 26.4 (25E246). I have modified the macOS Document App project template to showcase the issue. The project, along with a screen recording of the crash, can be downloaded from here: https://drive.google.com/drive/folders/1aDO34QleTm_rB9BuvVGjzzAP6jDXOc-o?usp=share_link Has anyone else experienced this? I'd like to know if this is a bug in the autosave feature of SwiftData and if I should file a bug report via Feedback Assistant. Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file linked above. Open the extracted "DocumentTest" project in Xcode. Build and run the "DocumentTest" app. In the document selection window, click "New Document" at the bottom-left. In the app, click the "+" button at the top-right to add a ParentItem with ChildItems. Click on the added ParentItem's button to modify one of its ChildItems. Repeat steps 5–6 until you have 5 ParentItems with a modified ChildItem. Press Command-Z 10 times to undo all the changes. Press Command-Shift-Z 10 times to redo all the changes. Repeat steps 8–9 until either the app crashes or some of the 5 ParentItems go missing in the list (you may have to repeat them 10–20 times before the issue occurs). If you change line 43 of ContentView.swift to modelContext.autosaveEnabled = false and repeat the same steps above, the app will not crash and no ParentItems will go missing. Code ParentItem Model @Model final class ParentItem { var timestamp: Date @Relationship( deleteRule: .cascade, inverse: \ChildItem.parentItem ) var childItems: [ChildItem] = [] init(timestamp: Date) { self.timestamp = timestamp } } ChildItem Model @Model final class ChildItem { var index: Int var isModified = false var parentItem: ParentItem? init(index: Int) { self.index = index } } Creating, Inserting, and Linking ParentItem and ChildItem // Create and insert ParentItem let newParentItem = ParentItem( timestamp: Date() ) modelContext.insert(newParentItem) // Create and insert ChildItems var newChildItems: [ChildItem] = [] for index in 0..<Int.random(in: 2...8) { let newChildItem = ChildItem(index: index) newChildItems.append(newChildItem) modelContext.insert(newChildItem) } /* Establish relationship between ParentItem and ChildItems */ newParentItem.childItems = newChildItems Modifying ChildItem let firstChildItem = parentItem.childItems .sorted(by: { $0.index < $1.index }).first if let firstChildItem, !firstChildItem.isModified { firstChildItem.isModified = true }
2
0
214
2w
CKSyncEngine: Duplicate FetchedRecordZoneChanges & Sync Handling Questions
Hi everyone, I've recently implemented CKSyncEngine in my app, and I have two questions regarding its behavior: Duplicate FetchedRecordZoneChanges After Sending Changes: I’ve noticed that the engine sometimes receives a FetchedRecordZoneChanges event containing modifications and deletions that were just sent by the same device a few moments earlier. This event arrives after the SentRecordZoneChanges event, and both events share the same recordChangeTag, which results in double-handling the record. Is this expected behavior? I’d like to confirm if this is how CKSyncEngine works or if I might be overlooking something. Handling Initial Sync with a "Sync Screen": When a user opens the app for the first time and already has data stored in iCloud, I need to display a "Sync Screen" temporarily to prevent showing partial data or triggering abrupt, rapid UI changes. I’ve found that canceling current operations, then awaiting sendChanges() and fetchChanges() works well to ensure data is fully synced before dismissing the sync screen: displaySyncScreen = true await syncEngine.cancelOperations() try await syncEngine.sendChanges() try await syncEngine.fetchChanges() displaySyncScreen = false However, I’m unsure if canceling operations like this could lead to data loss or other issues. Is this a safe approach, or would you recommend a better strategy for handling this initial sync state?
2
1
842
2w
Production Mac app becomes progressively unusable in Issues workspace; Mac_Dev remains fast
The production macOS build is showing severe performance problems, while Mac_Dev performs normally. Observed behavior in production Mac build: Issue board scrolling becomes inconsistent or nearly unusable Changing an issue status in detail view is very slow Scrolling the status menu/options can be slow Typing in issue description/notes fields becomes sluggish Dragging issues between milestones/statuses on the board can lag badly Observed behavior in Mac_Dev: Board scrolling is smooth Status changes are immediate Typing in description fields is responsive Drag/drop between milestones works well Important comparison: Mac_Dev appears to run against an isolated local SwiftData store Production Mac app uses the normal CloudKit-backed store Because the same UI is fast in Mac_Dev, this does not look like a pure rendering problem Most likely cause is production store / CloudKit sync churn amplifying existing SwiftUI invalidation and save behavior Current hypothesis: The production app is saving or observing live Issue mutations too aggressively Detail view edits and some quick actions may be causing repeated saves / broad view invalidation Cloud-backed persistence likely makes the problem much worse than the isolated dev store The UI architecture may still need cleanup, but the production data lane is likely a major factor Any help in understanding how best to address this would be helpful.
2
0
168
3w
TestFlight build crashes from fetch descriptor
I have a FetchDescriptor that uses starts(with:) which works fine in debug builds but crashes in TestFlight and archive. For background information I'm using iCloud and model inheritance where the property being used in fetch descriptor is defined on the superclass, the fetch descriptor is for the subclass. Implementation: static func fetchDescriptor(nameStartingWith prefix: String) -> FetchDescriptor<ColorAsset> { let predicate = #Predicate<ColorAsset> { asset in asset.name.starts(with: prefix) } return FetchDescriptor<ColorAsset>(predicate: predicate) } @Model public class Asset: Identifiable { // MARK: - Properties var name: String = "" .... } @available(macOS 26.0, *) @Model public class ColorAsset: Asset { ... }
2
0
157
3w
SwiftData document-based app broken
Hello all Synopsis: document based SwiftData app breaks document handling after first save due to internal error saving the -shm file. Long: i am working on a small document based SwiftData app for macOS. The UI works well as long as the document was not saved. After saving the document and reopening it, I get an error consistently in console: BUG IN CLIENT OF libsqlite3.dylib: database integrity compromised by API violation: vnode unlinked while in use: /Users/vrunkel/Library/Containers/de.ecoobs.CurtailmentAnalyzer/Data/tmp/TemporaryItems/NSIRD_CurtailmentAnalyzer_mrXKMs/NewDocument/StoreContent-shm So somehow the -shm file is still referenced to NewDocument created when the app opens an untitled document and resides in the temporary folder. I have saved the document to my documents folder. After reopening and the above error deletion or addition of items crashes the app with a long backtrace to view updating: Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread. I am not creating any threads or do background work. If I do not save the document but work within the new untitled document no problems occur. Even closing the app and reopening the untitled new doc (happens automatically) all is fine. To rule out any influence of my existing view structure I have created the most simple test case - Xcode -> New Project -> macOS document based app configured to use SwiftData. Same behaviour. After saving a new document the addition/deletion of items causes the thread-induced crash and shows the error in console when opening the document. I am using latest versions of Xcode 15.0 and macOS 14.0 Any ideas? thx, volker
9
2
2.6k
3w
Core Data Migration Strategy: store relocation, schema changes and CloudKit adoption in a single release?
I am planning a Core Data migration for a macOS app targeting macOS 12 and later and I would appreciate guidance on structuring the rollout to minimise risk. Context The app currently uses a SQLite store located at: ~/Library/Containers/com.company.AppName/Data/Library/Application Support/AppName I want to: Relocate the persistent store to an app group container: ~/Library/Group Containers/group.com.company.AppName Perform schema migration, including: Renaming attributes Deleting attributes Using a custom NSEntityMigrationPolicy subclass Adopt iCloud sync using NSPersistentCloudKitContainer Potentially leverage staged migration (macOS 14+) Additionally, I intend to port the app to iOS, so the end state needs to support an app group container and CloudKit with the latest schema from the outset. Questions Store relocation vs schema migration Is it advisable to perform store relocation and schema migration in a single step, or should these be separate releases? If combined, are there pitfalls when moving the SQLite file and running a migration in the same launch cycle? Custom migration policy Any best practices for structuring NSEntityMigrationPolicy when also relocating the store? Should migration policies assume the store has already been moved, or handle both concerns? Staged migration (macOS 14+) Is staged migration worth adopting when still supporting macOS 12–13? Would you gate it conditionally, or avoid it entirely for consistency? CloudKit adoption Is introducing NSPersistentCloudKitContainer in the same release as the above migrations too risky? Are there known issues when enabling CloudKit immediately after a migration? Release strategy Would you recommend: A single release handling everything Two phases: (1) store & schema migration, (2) CloudKit Or three phases: store relocation → schema migration → CloudKit Goal I want a smooth, reliable transition without data loss or duplication, particularly for existing users with non-trivial datasets. Any insights, practical experience, or recommended sequencing strategies would be very helpful.
3
0
158
3w
CoreData + CloudKit -- Many-to-Many Relationship not Syncing
In an iOS App that uses CKShare I have a many-to-many relationship that does not consistently sync between the share's N participants. The relationship is between Group and Player as group.players and player.groups. As an example, given 3 group each with 4 players (aka 4:4:4), some devices show CoreData (it is NOT a UI issue) with 4:2:3 or 3:4:4. (A deletion of CoreData from a device, forcing a full re-sync from CloudKit, seems to populate the group:player relationships consistently; but obviously that is impractical to resolving the issue). How do I avoid these sync-from-CloudKit inconsistencies? Note: AI agents generally suggest adding a CoreData 'join' entity - such as 'GroupPlayer'. Is that THE fix?
1
0
112
3w
Best practice for centralizing SwiftData query logic and actions in an @Observable manager?
I'm building a SwiftUI app with SwiftData and want to centralize both query logic and related actions in a manager class. For example, let's say I have a reading app where I need to track the currently reading book across multiple views. What I want to achieve: @Observable class ReadingManager { let modelContext: ModelContext // Ideally, I'd love to do this: @Query(filter: #Predicate<Book> { $0.isCurrentlyReading }) var currentBooks: [Book] // ❌ But @Query doesn't work here var currentBook: Book? { currentBooks.first } func startReading(_ book: Book) { // Stop current book if any if let current = currentBook { current.isCurrentlyReading = false } book.isCurrentlyReading = true try? modelContext.save() } func stopReading() { currentBook?.isCurrentlyReading = false try? modelContext.save() } } // Then use it cleanly in any view: struct BookRow: View { @Environment(ReadingManager.self) var manager let book: Book var body: some View { Text(book.title) Button("Start Reading") { manager.startReading(book) } if manager.currentBook == book { Text("Currently Reading") } } } The problem is @Query only works in SwiftUI views. Without the manager, I'd need to duplicate the same query in every view just to call these common actions. Is there a recommended pattern for this? Or should I just accept query duplication across views as the intended SwiftUI/SwiftData approach?
3
0
596
4w
Fatal error on rollback after delete
I encountered an error when trying to rollback context after deleting some model with multiple one-to-many relationships when encountered a problem later in a deleting method and before saving the changes. Something like this: do { // Fetch model modelContext.delete(model) // Do some async work that potentially throws try modelContext.save() } catch { modelContext.rollback() } When relationship is empty - the parent has no children - I can safely delete and rollback with no issues. However, when there is even one child when I call even this code: modelContext.delete(someModel) modelContext.rollback() I'm getting a fatal error: SwiftData/ModelSnapshot.swift:46: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<ChildModel> I use ModelContext from within the ModelActor but using mainContext changes nothing. My ModelContainer is quite simple and problem occurs on both in-memory and persistent storage, with or without CloudKit database being enabled. I can isolate the issue in test environment, so the model that's being deleted (or any other) is not being accessed by any other part of the application. However, problem looks the same in the real app. I also changed the target version of iOS from 18.0 to 26.0, but to no avail. My models look kind of like this: @Model final class ParentModel { var name: String @Relationship(deleteRule: .cascade, inverse: \ChildModel.parent) var children: [ChildModel]? init(name: String) { self.name = name } } @Model final class ChildModel { var name: String @Relationship(deleteRule: .nullify) var parent: ParentModel? init(name: String) { self.name = name } } I tried many approaches that didn't help: Fetching all children (via fetch) just to "populate" the context Accessing all children on parent model (via let _ = parentModel.children?.count) Deleting all children reading models from parent: for child in parentModel.children ?? [] { modelContext.delete(child) } Deleting all children like this: let parentPersistentModelID = parentModel.persistentModelID modelContext.delete(model: ChildModel.self, where: #Predicate { $0.parent.persistentModelID == parentPersistentModelID }, includeSubclasses: true) Removing @Relationship(deleteRule: .nullify) from ChildModel relationship definition I found 2 solution for the problem: To manually fetch and delete all children prior to deleting parent: let parentPersistentModelID = parentModel.persistentModelID for child in try modelContext.fetch(FetchDescriptor<ChildModel>(predicate: #Predicate { $0.parent.persistentModelID == parentPersistentModelID })) { modelContext.delete(child) } modelContext.delete(parentModel) Trying to run my code in child context (let childContext = ModelContext(modelContext.container)) All that sounds to me like a problem deep inside Swift Data itself. The first solution I found, fetching potentially hundreds of child models just to delete them in case I might need to rollback changes on some error, sounds like awful waste of resources to me. The second one however seems to work fine has that drawback that I can't fully test my code. Right now I can wrap the context (literally creating class that holds ModelContext and calls its methods) and in tests for throwing methods force them to throw. By creating scratch ModelContext I loose that possibility. What might be the real issue here? Am I missing something?
2
0
207
4w
iCloud Drive silent upload deadlock caused by stale HTTP/3 session in nsurlsessiond (FB22476701)
Summary On macOS 26.4.1 (25E253), iCloud Drive file uploads can enter a silent deadlock where every upload attempt fails at the transport layer. No error is surfaced anywhere — not in Finder, not in System Settings, not in the iCloud status panel. The upload queue simply stops. Other iCloud services (Photos, Mail, App Store) continue to work normally through the same networking infrastructure at the same time. Root Cause The issue is a stale HTTP/3 (QUIC) session cached in the user-level nsurlsessiond process's BackgroundConnectionPool. The deadlock cycle: cloudd requests an upload to the GCS storage endpoint nsurlsessiond provides the cached (broken) HTTP/3 session The TLS handshake succeeds, but the body upload dies mid-transfer (err=T, requestDuration=-1.000, responseHeaderBytes=0) cloudd retries with a new connectionUUID — but nsurlsessiond still routes through the same poisoned QUIC session This repeats indefinitely Killing cloudd alone does not help — nsurlsessiond retains the poisoned pool. Only killing both the user-level cloudd and nsurlsessiond clears the pool and forces a fresh protocol negotiation. The Smoking Gun After killing both daemons, the system falls back to HTTP/1.1 for the stuck uploads — and they complete instantly: Before Kill After Kill Protocol h3 (QUIC) http/1.1 (TCP) Largest upload Failed at partial offsets 26 MB in 1.6 seconds Server response 0 bytes 596 bytes (normal) Same endpoint, same files, same network interface (en5), same power state. The only change was the protocol negotiation after a fresh nsurlsessiond. Reproduction Reproduced 3 times on April 11, 2026 using a standardized set of 8 test files (8 bytes to 20 MB) in a non-shared iCloud Drive folder. Each run showed the identical pattern: Small files (<100 KB) squeeze through before the QUIC session stalls Larger files trigger the deadlock every time 5–6 retries with fresh connectionUUIDs, all failing over protocol=h3 After kill cloudd + nsurlsessiond: immediate flush via protocol=http/1.1 An automated evidence-collection script (collect_h3_deadlock_evidence.sh) captures paired before-kill / after-kill logs. Included in the Feedback report. Symptom Check (for others hitting this) /usr/bin/log show --predicate 'process == "cloudd"' --last 5m 2>&1 \ | grep "putContainer.*err=T.*requestDuration=-1.000.*protocol=h3" | wc -l Output > 0 = this deadlock. Output = 0 = different issue. Recovery (one-liner) kill $(ps -axo user,pid,command | awk -v u="$USER" \ '($1==u && /CloudKitDaemon.framework.*cloudd/ && !/--system/) \ || ($1==u && /\/usr\/libexec\/nsurlsessiond/ && !/--privileged/) \ {print $2}') Both daemons respawn within 1–2 seconds. Do not use killall nsurlsessiond — it would also kill the privileged system instance. What was ruled out Network connectivity (Photos uploaded 8 MB through the same pool simultaneously) iCloud account (metadata operations succeeding, only body uploads failing) File type/content (random data, correlation is with size, not type) Storage quota (1.65 TB free) CFNetworkHTTP3Enabled=false (key is ineffective in 26.4.1) Suggested fixes (from the Feedback report) CFNetwork: Invalidate the QUIC session after N consecutive requestDuration=-1.000 failures CloudKit/NSURLSession: Expose a pool invalidation API like [NSURLSession invalidatePoolEntryForEndpoint:] cloudd: Self-healing retry — create a fresh NSURLSession after M consecutive deadlock-signature failures Finder: At minimum, surface the stuck state to the user instead of failing silently Filed as FB22476701 — includes full reproduction timelines, request/connection UUIDs, sysdiagnose, and a 12-page investigation PDF with architecture diagrams and protocol comparison tables. If you're experiencing the same issue, please file a duplicate referencing FB22476701 — Apple prioritizes by duplicate count. System MacBook Air, macOS 26.4.1 (25E253) iCloud Drive with Desktop & Documents sync en0 (WLAN) + en5 (USB-LAN via Studio Display)
Replies
7
Boosts
0
Views
289
Activity
1d
Sandboxed app loses iCloud Drive access mid-session on macOS 26 — kernel refuses sandbox extension, FP client rejected (NSFileProviderErrorDomain -2001)
Starting somewhere around macOS 26.3, my sandboxed file manager spontaneously loses access to ~/Library/Mobile Documents mid-session. Setup: at launch, the user grants access to '/', '/Users', or '~' via NSOpenPanel; I store a security-scoped bookmark and call startAccessingSecurityScopedResource(). This works fine - including iCloud Drive - until some point mid-session. When it breaks, two things happen simultaneously: Enumeration fails: NSCocoaErrorDomain Code=257 (NSFileReadNoPermissionError)< NSPOSIXErrorDomain Code=1 (EPERM) Console shows the kernel refusing extension issuance: couldn't issue sandbox extension com.apple.app-sandbox.read for '/Users//Library/Mobile Documents': Operation not permitted And probing NSFileProviderManager confirms the process has been rejected system-wide: NSFileProviderManager.getDomainsWithCompletionHandler > NSFileProviderErrorDomain Code=-2001 "The application cannot be used right now." (underlying Code=-2014) What makes this specific to FP-backed paths: regular paths under the same '/' bookmark (~/Library/Application Support, etc.) stay accessible and recover normally with a fresh startAccessingSecurityScopedResource() call. Only ~/Library/Mobile Documents and its subtree fail - the entire tree, including the parent directory itself. Relaunch always restores access. What I've tried and ruled out: Re-resolving the bookmark + startAccessingSecurityScopedResource() - returns stale=false, granted=true but access is not restored; the kernel still refuses extension issuance for FP-traversing paths. NSFileCoordinator coordinated read - doesn't help; the coordinator depends on the same sandbox extension the kernel is refusing. Instantiating NSFileProviderManager(for: domain) per domain - fails with -2001 for every domain, confirming the rejection is process-wide, not path- or domain-specific. My working theory: when a FileProvider daemon (bird/cloudd/fileproviderd) restarts mid-session, the process's FP-client XPC registration is invalidated, and the kernel subsequently refuses to issue sandbox extensions for any path served by FP - even with a valid bookmark. The process seems to have no API path to re-register its FP-client identity without relaunching. Current workaround: I detect the -2001 response and prompt the user to relaunch, then do a programmatic self-relaunch if they confirm (which is obviously horribly intrusive). Questions: Is there an API that lets a sandboxed consumer app reconnect its FP-client identity mid-session, short of relaunching? Is there an entitlement or capability that would make the kernel's extension issuance resilient to FP daemon restarts? Has anyone else hit this on 26.x and found a workaround? Filed as FB22547671.
Replies
3
Boosts
0
Views
88
Activity
1d
CloudKit private database operations fail with CKError 15 / HTTP 500 for one container across multiple apps (FB22539748)
We are seeing a CloudKit private database failure for this specific container: iCloud.com.matrixqlc.photodiet.sync Failure pattern: accountStatus succeeds in some cases ensure/create custom zone succeeds but record/database-level operations consistently fail with: CKErrorDomain code = 15 CKInternalErrorDomain code = 2000 HTTP 500 Failing operations include: allRecordZones() databaseChanges(since:nil) allSubscriptions() fetch record zone metadata save record fetch record query records What makes this unusual is that the issue follows the container, not the app. On the same physical device, same Apple ID, same developer team: PhotoDiet + iCloud.com.matrixqlc.photodiet.sync => fails RepaymentCalculator + iCloud.com.matrixqlc.photodiet.sync => fails PhotoDiet + iCloud.com.matrixqlc.repaymentcalculator.sync2 => succeeds RepaymentCalculator + iCloud.com.matrixqlc.repaymentcalculator.sync2 => succeeds So this does not currently look like: app-specific entitlement/provisioning issues device/account issues CloudKit API misuse in one app record schema or app business logic issues It currently looks like the container iCloud.com.matrixqlc.photodiet.sync itself may be in a bad backend state. Sample request identifiers: RequestUUID: C8403047-0037-4D36-A7A7-CF3C83584A42 RequestUUID: 04437D9D-115E-45F5-87B5-A8CD146AE705 RequestUUID: C924B620-BAEE-403D-B944-151ADCF3419F RequestUUID: A54E79E1-6037-4533-BA09-18FBC436851C RequestUUID: 3EFD8913-3781-47CF-A48C-B651BF38EA50 RequestUUID: 2677A991-40B3-42AB-9CE5-3C4F1288EE08 Feedback Assistant ID: FB22539748 Has anyone seen a container-specific CloudKit private database failure like this, where multiple apps under the same team can access one container normally but consistently fail on another container with CKError 15 / HTTP 500?
Replies
1
Boosts
0
Views
47
Activity
3d
SwiftData document-based app crashes on undo/redo without ModelContext.transaction(block:)
Overview I'm developing a document-based app for macOS using SwiftData. When I undo/redo changes using Command-Z/Command-Shift-Z, the app reliably crashes with the following error: SwiftData/ModelSnapshot.swift:46: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<DocumentTest.ChildItem> And before the app crashes, what always happens is that UndoManager stops removing/restoring instances of ChildItem (but continues to remove/restore instances of ParentItem). The issue goes away when I enclose the relevant code in ModelContext.transaction(block:). However, this shouldn't be necessary, as ModelContext.autosaveEnabled is true by default. The issues are occurring with Xcode 26.4 (17E192) and macOS Tahoe 26.4 (25E246). I have modified the macOS Document App project template to showcase the issue. The sample project, along with a screen recording of the crash, can be downloaded from here: https://drive.google.com/drive/folders/13bCB1qRZ6273BI81zW2zUUBraSvv6p5w?usp=share_link Is this expected behavior or should I file a bug report in Feedback Assistant? Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file linked above. Open the extracted "DocumentTest" project in Xcode. Build and run the "DocumentTest" app. In the document selection window, click "New Document" at the bottom-left. In the app, click the "+" button at the top-right to add a ParentItem with ChildItems. Click on the added ParentItem's button to add another ChildItem to it. Repeat steps 5–6 until you have 5 ParentItems with an additional ChildItem. Press Command-Z 10 times to undo all the changes. Press Command-Shift-Z 10 times to redo all the changes. Repeat steps 8–9 until UndoManager stops removing/restoring the additional ChildItem, and continue repeating them until the app eventually crashes (you may have to repeat them 5–10 times before the issue occurs). If you uncomment the ModelContext.transaction(block:) at line 13 of ContentView.swift and repeat the same steps above, no ChildItems will go missing and the app will not crash. Code ParentItem Model @Model final class ParentItem { var timestamp: Date @Relationship( deleteRule: .cascade, inverse: \ChildItem.parentItem ) var childItems: [ChildItem] = [] init(timestamp: Date) { self.timestamp = timestamp } } ChildItem Model @Model final class ChildItem { var index: Int var parentItem: ParentItem? init(index: Int) { self.index = index } } Creating, Inserting, and Linking ParentItem and ChildItem // Create and insert ParentItem let newParentItem = ParentItem( timestamp: Date() ) modelContext.insert(newParentItem) // Create and insert ChildItems var newChildItems: [ChildItem] = [] for index in 0..<Int.random(in: 2...8) { let newChildItem = ChildItem(index: index) newChildItems.append(newChildItem) modelContext.insert(newChildItem) } /* Establish relationship between ParentItem and ChildItems */ for newChildItem in newChildItems { newParentItem.childItems.append( newChildItem ) newChildItem.parentItem = newParentItem } Adding an Additional ChildItem to ParentItem // Uncommenting this block fixes the crash // try! modelContext.transaction { // Create and insert the new ChildItem let newChildItem = ChildItem( index: parentItem.childItems.count ) modelContext.insert(newChildItem) // Establish relationship to parentItem parentItem.childItems.append(newChildItem) newChildItem.parentItem = parentItem // }
Replies
3
Boosts
0
Views
238
Activity
5d
CKRecordZone deleted when second user accepts zone-wide CKShare
I'm seeing a critical issue where a custom CKRecordZone is consistently deleted server-side when a second iCloud account interacts with a zone-wide CKShare. I've reproduced this 20+ times across two days and have exhausted every client-side fix I can think of. Looking for guidance on what might be going wrong. Setup Container: iCloud.com.cohencooks (production app on App Store) Custom CKRecordZone in owner's private database Zone-wide CKShare(recordZoneID:) (iOS 15+ zone sharing) SwiftData with ModelConfiguration(cloudKitDatabase: .none) — no automatic CloudKit mirroring Acceptance via CKFetchShareMetadataOperation → CKContainer.accept(metadata) (no UICloudSharingController) Minimal reproduction // 1. Owner creates zone + share let zone = CKRecordZone(zoneName: "MyZone") try await privateDB.save(zone) let share = CKShare(recordZoneID: zone.zoneID) share[CKShare.SystemFieldKey.title] = "My Share" as CKRecordValue share.publicPermission = .readWrite let (results, _) = try await privateDB.modifyRecords(saving: [share], deleting: []) // 2. Owner pushes ~500 records to zone — all succeed // 3. Second user (different iCloud account) accepts share let metadata = try await container.shareMetadata(for: shareURL) try await container.accept(metadata) // 4. Owner's next CKFetchRecordZoneChangesOperation → zoneNotFound (code 26) // Zone is permanently gone. allRecordZones() confirms deletion. What I observe Three distinct failure patterns depending on configuration: Pattern 1 — publicPermission = .readWrite, no addParticipant: Zone dies instantly after acceptance. First push notification shows cloudkit.share changed (zone alive), second push notification returns zoneNotFound. The non-owner never successfully wrote anything. Pattern 2 — publicPermission = .none with explicit addParticipant: Zone survives acceptance and 2-3 minutes of bidirectional sync (non-owner pulls 578 records, pushes meal plans back). Then a push notification arrives and the zone is gone. This is dramatically better than Pattern 1 but still fails. Pattern 3 — Container destabilization after repeated testing: After 20+ create/delete cycles in one day, zones die from the owner's own push notifications — no second device involved at all. The container appears to enter an unstable state. What I've ruled out Hypothesis Test Result publicPermission = .readWrite Changed to .none + explicit addParticipant Zone survived longer but still eventually deleted Zone name tombstoning Tested 6 fresh names never used in this container All eventually deleted Non-owner writes causing deletion Gated ALL non-owner push methods (recipe, meal plan, grocery, photo, event) Zone still deleted database.save(share) vs modifyRecords Switched to modifyRecords(saving:deleting:) Zone still deleted NSPersistentCloudKitContainer interference Removed all Core Data CloudKit code Zone still deleted Double share acceptance Fresh app install, single acceptance only Zone still deleted Advanced Data Protection Neither account has ADP enabled Not the cause Programmatic vs system acceptance Tested both container.accept() and tapping share link Zone still deleted CloudKit Dashboard No ZoneDelete operation is visible in the logs. All operations are ZoneFetch, ZoneChanges, RecordQuery, RecordFetch. I do see EphemeralGroup operations targeting the custom zone — not sure what generates those. Comparison with working apps I compared my implementation with another app (Spotbook) that uses the exact same zone-wide CKShare(recordZoneID:) pattern with publicPermission = .readWrite and programmatic acceptance — and it works. The main difference is that app uses CKSyncEngine (iOS 17+) rather than raw CKFetchRecordZoneChangesOperation / CKModifyRecordsOperation. Could CKSyncEngine be handling something internally that prevents this issue? Questions Is there a known interaction between zone-wide CKShare(recordZoneID:) acceptance and zone lifecycle that could cause zone deletion? Does CKSyncEngine handle zone-wide sharing differently than manual CKFetchRecordZoneChangesOperation + CKModifyRecordsOperation? What generates EphemeralGroup operations in CloudKit Dashboard? Could these trigger a zone delete? After 20+ zone create/delete cycles in a container, is there a server-side rate limit or tombstone mechanism that would destabilize new zones? Is the custom programmatic acceptance flow (CKFetchShareMetadataOperation → container.accept()) fully supported for zone-wide shares, or does it require UICloudSharingController? Any guidance would be greatly appreciated. This is blocking multi-user functionality for our app (mesa, a meal planning app on the App Store). Single-user sync works perfectly — the issue only manifests when a second iCloud account is involved. Environment: iOS 18.4.1, Xcode 16+, Swift, SwiftUI
Replies
3
Boosts
0
Views
105
Activity
6d
CKRecordZone deleted when second user accepts zone-wide CKShare
I'm seeing a critical issue where a custom CKRecordZone is consistently deleted server-side when a second iCloud account interacts with a zone-wide CKShare. I've reproduced this 20+ times across two days and have exhausted every client-side fix I can think of. Looking for guidance on what might be going wrong. Setup Container: iCloud.com.cohencooks (production app on App Store) Custom CKRecordZone in owner's private database Zone-wide CKShare(recordZoneID:) (iOS 15+ zone sharing) SwiftData with ModelConfiguration(cloudKitDatabase: .none) — no automatic CloudKit mirroring Acceptance via CKFetchShareMetadataOperation → CKContainer.accept(metadata) (no UICloudSharingController) Minimal reproduction // 1. Owner creates zone + share let zone = CKRecordZone(zoneName: "MyZone") try await privateDB.save(zone) let share = CKShare(recordZoneID: zone.zoneID) share[CKShare.SystemFieldKey.title] = "My Share" as CKRecordValue share.publicPermission = .readWrite let (results, _) = try await privateDB.modifyRecords(saving: [share], deleting: []) // 2. Owner pushes ~500 records to zone — all succeed // 3. Second user (different iCloud account) accepts share let metadata = try await container.shareMetadata(for: shareURL) try await container.accept(metadata) // 4. Owner's next CKFetchRecordZoneChangesOperation → zoneNotFound (code 26) // Zone is permanently gone. allRecordZones() confirms deletion. What I observe Three distinct failure patterns depending on configuration: Pattern 1 — publicPermission = .readWrite, no addParticipant: Zone dies instantly after acceptance. First push notification shows cloudkit.share changed (zone alive), second push notification returns zoneNotFound. The non-owner never successfully wrote anything. Pattern 2 — publicPermission = .none with explicit addParticipant: Zone survives acceptance and 2-3 minutes of bidirectional sync (non-owner pulls 578 records, pushes meal plans back). Then a push notification arrives and the zone is gone. This is dramatically better than Pattern 1 but still fails. Pattern 3 — Container destabilization after repeated testing: After 20+ create/delete cycles in one day, zones die from the owner's own push notifications — no second device involved at all. The container appears to enter an unstable state. Inconsistent state after deletion Here's something that might help narrow this down. After one of the zone deletions, I deployed the same build to a second device signed into a different iCloud account that had previously accepted the CKShare. Without sending a new invite, that device found the "Household" zone via allRecordZones() on sharedCloudDatabase — it could pull all 578 records, push updates, and the share URL still resolved. Meanwhile, the owner device (zone creator) gets "zone not found" from both allRecordZones() and direct recordZone(for:) on privateCloudDatabase. So it looks like the zone is deleted from the owner's private database, but the CKShare and zone records remain accessible to participants via the shared database. Participants can still read and write as if nothing happened — the owner just can't see the zone anymore. This also creates a recovery problem — when the owner creates a new zone with the same name, it gets a new CKShare URL, but the participant is still connected to the old "ghost" zone. The two sides are permanently split. Does this mean the zone deletion is happening through a path that doesn't properly clean up the sharing infrastructure? Is this expected behavior when a zone-wide CKShare's zone is deleted, or does it suggest the deletion is happening through an abnormal server-side path? What I've ruled out Hypothesis Test Result publicPermission = .readWrite Changed to .none + explicit addParticipant Zone survived longer but still eventually deleted Zone name tombstoning Tested 6 fresh names never used in this container All eventually deleted Non-owner writes causing deletion Gated ALL non-owner push methods (recipe, meal plan, grocery, photo, event) Zone still deleted database.save(share) vs modifyRecords Switched to modifyRecords(saving:deleting:) Zone still deleted NSPersistentCloudKitContainer interference Removed all Core Data CloudKit code Zone still deleted Double share acceptance Fresh app install, single acceptance only Zone still deleted Advanced Data Protection Neither account has ADP enabled Not the cause Programmatic vs system acceptance Tested both container.accept() and tapping share link Zone still deleted CloudKit Dashboard No ZoneDelete operation is visible in the logs. All operations are ZoneFetch, ZoneChanges, RecordQuery, RecordFetch. I do see EphemeralGroup operations targeting the custom zone — not sure what generates those. Comparison with working apps I compared my implementation with another app that uses the exact same zone-wide CKShare(recordZoneID:) pattern with publicPermission = .readWrite and programmatic acceptance — and it works. The main difference is that app uses CKSyncEngine (iOS 17+) rather than raw CKFetchRecordZoneChangesOperation / CKModifyRecordsOperation. Could CKSyncEngine be handling something internally that prevents this issue? Questions Is there a known interaction between zone-wide CKShare(recordZoneID:) acceptance and zone lifecycle that could cause zone deletion? Does CKSyncEngine handle zone-wide sharing differently than manual CKFetchRecordZoneChangesOperation + CKModifyRecordsOperation? What generates EphemeralGroup operations in CloudKit Dashboard? Could these trigger a zone delete? After 20+ zone create/delete cycles in a container, is there a server-side rate limit or tombstone mechanism that would destabilize new zones? Is the inconsistent state I described (zone gone from owner's private DB but still accessible from participant's shared DB) expected behavior, or does it indicate the deletion is happening through an abnormal path? Is the custom programmatic acceptance flow (CKFetchShareMetadataOperation → container.accept()) fully supported for zone-wide shares, or does it require UICloudSharingController? Any guidance would be greatly appreciated. This is blocking multi-user functionality for our app (mesa, a meal planning app on the App Store). Single-user sync works perfectly — the issue only manifests when a second iCloud account is involved. Environment: iOS 18.4.1, Xcode 16+, Swift, SwiftUI
Replies
1
Boosts
0
Views
85
Activity
1w
SwiftData property marked ephemeral getting persisted in CloudKit
Am I misunderstanding the expected behavior here, or is there a bug in the behavior of @Attribute(.ephemeral) tagged SwiftData model properties? The documentation for .ephemeral says "Track changes to this property but do not persist". I started using .ephemeral because @Transient was inhibiting SwiftUI from reacting to changes to the property through @Observable. I am updating the value of my @Attribute(.ephemeral) property about once a second and I am seeing corresponding console log output showing the property as part of the generated CKRecord object. I then confirmed in the CloudKit dev portal that the .ephemeral property was added to the Record schema and contains real values. The behavior seems as though the .ephemeral property is being completely ignored. This is observed in a new Xcode project using SwiftData with CloudKit, Xcode 16.2, macOS 15.3.1 and during Build & Run testing on physical devices.
Replies
3
Boosts
1
Views
843
Activity
1w
Does CKSyncEngine have to be re-initialized after an account change event?
According to this comment in the sample project on GitHub and this answer by Apple Staff, CKSyncEngine should be re-initialized after signing out or switching accounts so that "CKSyncEngine schedules a new fetch on init." But according to my tests, CKSyncEngine will schedule a fetch after having a signed out and signed in again, without me ever having to reset the serialized sync state. The documentation doesn't mentioned anywhere that CKSyncEngine should be re-initialized after an account change. In fact, it states that CKSyncEngine will reset its state internally on account changes. So if that's the case, then I'm very confused as to why the "official" recommendation is to re-initialize CKSyncEngine after receiving .signOut or .accountSwitch. Can someone please clarify the correct approach here?
Replies
1
Boosts
0
Views
183
Activity
1w
iCloud Sync not working with iPhone, works fine for Mac.
I've been working on an app. It uses iCloud syncing. 48 hours ago everything was working 100%. Make a change on the iPhone it immediately changed on the Mac. Change on the Mac, it immediately changed on the iPhone. I didn't work on it yesterday. I updated to iOS26.4 on the iPhone and 26.4 on the Mac yesterday instead. Today, I pull up the project again. I made NO changes to the code or settings. Make a change on the iPhone it immediately updates on the Mac. Make a change on the Mac, nothing happens on the iPhone. I've waited an hour, and the change never happens. If you leave the iPhone app, then return, it updates as it should. It appears that iCloud's silent notification is to being received by the iPhone. Anyone else having the issue? Is there something new with iOS 26.4 that needs to be adjusted to get this to work? Again, works flawlessly with the Mac, just not with the iPhone.
Replies
36
Boosts
17
Views
8.3k
Activity
1w
SwiftData document-based app crashes on undo/redo without ModelContext.transaction(block:)
Overview I'm developing a document-based app for macOS using SwiftData. When I undo/redo changes using Command-Z/Command-Shift-Z, the app reliably crashes with the following error: SwiftData/ModelSnapshot.swift:46: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<DocumentTest.ChildItem> And before the app crashes, what always happens is that UndoManager stops removing/restoring instances of ChildItem (but continues to remove/restore instances of ParentItem). The issue goes away when I enclose the relevant code in ModelContext.transaction(block:). However, this shouldn't be necessary, as ModelContext.autosaveEnabled is true by default. The issues are occurring with Xcode 26.4 (17E192) and macOS Tahoe 26.4 (25E246). I have modified the macOS Document App project template to showcase the issue. The sample project, along with a screen recording of the crash, can be downloaded from here: https://drive.google.com/drive/folders/13bCB1qRZ6273BI81zW2zUUBraSvv6p5w?usp=share_link Is this expected behavior or should I file a bug report in Feedback Assistant? Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file linked above. Open the extracted "DocumentTest" project in Xcode. Build and run the "DocumentTest" app. In the document selection window, click "New Document" at the bottom-left. In the app, click the "+" button at the top-right to add a ParentItem with ChildItems. Click on the added ParentItem's button to add another ChildItem to it. Repeat steps 5–6 until you have 5 ParentItems with an additional ChildItem. Press Command-Z 10 times to undo all the changes. Press Command-Shift-Z 10 times to redo all the changes. Repeat steps 8–9 until UndoManager stops removing/restoring the additional ChildItem, and continue repeating them until the app eventually crashes (you may have to repeat them 5–10 times before the issue occurs). If you uncomment the ModelContext.transaction(block:) at line 13 of ContentView.swift and repeat the same steps above, no ChildItems will go missing and the app will not crash. Code ParentItem Model @Model final class ParentItem { var timestamp: Date @Relationship( deleteRule: .cascade, inverse: \ChildItem.parentItem ) var childItems: [ChildItem] = [] init(timestamp: Date) { self.timestamp = timestamp } } ChildItem Model @Model final class ChildItem { var index: Int var parentItem: ParentItem? init(index: Int) { self.index = index } } Creating, Inserting, and Linking ParentItem and ChildItem // Create and insert ParentItem let newParentItem = ParentItem( timestamp: Date() ) modelContext.insert(newParentItem) // Create and insert ChildItems var newChildItems: [ChildItem] = [] for index in 0..<Int.random(in: 2...8) { let newChildItem = ChildItem(index: index) newChildItems.append(newChildItem) modelContext.insert(newChildItem) } /* Establish relationship between ParentItem and ChildItems */ for newChildItem in newChildItems { newParentItem.childItems.append( newChildItem ) newChildItem.parentItem = newParentItem } Adding an Additional ChildItem to ParentItem // Uncommenting this block fixes the crash // try! modelContext.transaction { // Create and insert the new ChildItem let newChildItem = ChildItem( index: parentItem.childItems.count ) modelContext.insert(newChildItem) // Establish relationship to parentItem parentItem.childItems.append(newChildItem) newChildItem.parentItem = parentItem // }
Replies
1
Boosts
0
Views
137
Activity
1w
CKQuerySubscription on public database never triggers APNS push in Production environment
Hi everyone, I have a SwiftUI app using CKQuerySubscription on the public database for social notifications (friend requests, recommendations, etc.). Push notifications work perfectly in the Development environment but never fire in Production (TestFlight). Setup: iOS 26.4, Xcode 26, Swift 6 Container: public database, CKQuerySubscription with .firesOnRecordCreation 5 subscriptions verified via CKDatabase.allSubscriptions() registerForRemoteNotifications() called unconditionally on every launch Valid APNS device token received in didRegisterForRemoteNotificationsWithDeviceToken Push Notifications + Background Modes (Remote notifications) capabilities enabled What works: All 5 subscriptions create successfully in Production Records are saved and queryable (in-app CloudKit fetches return them immediately) APNS production push works — tested via Xcode Push Notifications Console with the same device token, notification appeared instantly Everything works perfectly in the Development environment (subscriptions fire, push arrives) What doesn't work: When a record is created that matches a subscription predicate, no APNS push is ever delivered in Production Tested with records created from the app (device to device) and from CloudKit Dashboard — neither triggers push Tried: fresh subscription IDs, minimal NotificationInfo (just alertBody), stripped shouldSendContentAvailable, created an APNs key, toggled Push capability in Xcode, re-deployed schema from dev to prod Additional finding: One of my record types (CompletionNotification) was returning BAD_REQUEST when creating a subscription in Production, despite working in Development. Re-deploying the development schema to production (which reported "no changes") fixed the subscription creation. This suggests the production environment had inconsistent subscription state for that record type, possibly from the type being auto-created by a record save before formal schema deployment. I suspect a similar issue may be affecting the subscription-to-APNS pipeline for all my record types — the subscriptions exist and predicates match, but the production environment isn't wiring them to APNS delivery. Subscription creation code (simplified): let subscription = CKQuerySubscription( recordType: "FriendRequest", predicate: NSPredicate(format: "receiverID == %@ AND status == %@", userID, "pending"), subscriptionID: "fr-sub-v3", options: [.firesOnRecordCreation] ) let info = CKSubscription.NotificationInfo() info.titleLocalizationKey = "Friend Request" info.alertLocalizationKey = "FRIEND_REQUEST_BODY" info.alertLocalizationArgs = ["senderUsername"] info.soundName = "default" info.shouldBadge = true info.desiredKeys = ["senderUsername", "senderID"] info.category = "FRIEND_REQUEST" subscription.notificationInfo = info try await database.save(subscription) Has anyone encountered this? Is there a way to "reset" the subscription-to-APNS pipeline for a production container? I'd really appreciate any guidance on how to resolve and get my push notifications back to normal. Many thanks, Dimitar - LaterRex
Replies
11
Boosts
1
Views
1.1k
Activity
2w
SwiftData document-based app crashes on undo/redo with autosaveEnabled
Overview I'm developing a document-based app for macOS using SwiftData. When I undo/redo changes using Command-Z/ Command-Shift-Z, the app randomly crashes with the following error: SwiftData/BackingData.swift:425: Fatal error: Failed to retrieve the identifier for \ChildItem.parentItem from KnownKeysDictionary:KnownKeysMap: ["parentItem": 2, "isModified": 1, "index": 0] values: [Optional(0), Optional(false), Optional(DocumentTest.ParentItem)] SwiftData._KKMDBackingData<DocumentTest.ChildItem> And sometimes, instead of the app crashing, my created @Model objects simply disappear. They do not reappear in the @Query on undo/redo. Both of these issues go away when I set modelContext.autosaveEnabled = false The issues are occurring with Xcode 26.4 (17E192) and macOS Tahoe 26.4 (25E246). I have modified the macOS Document App project template to showcase the issue. The project, along with a screen recording of the crash, can be downloaded from here: https://drive.google.com/drive/folders/1aDO34QleTm_rB9BuvVGjzzAP6jDXOc-o?usp=share_link Has anyone else experienced this? I'd like to know if this is a bug in the autosave feature of SwiftData and if I should file a bug report via Feedback Assistant. Steps to Reproduce To recreate the issue, follow these steps: Download and extract the "Xcode Project.zip" file linked above. Open the extracted "DocumentTest" project in Xcode. Build and run the "DocumentTest" app. In the document selection window, click "New Document" at the bottom-left. In the app, click the "+" button at the top-right to add a ParentItem with ChildItems. Click on the added ParentItem's button to modify one of its ChildItems. Repeat steps 5–6 until you have 5 ParentItems with a modified ChildItem. Press Command-Z 10 times to undo all the changes. Press Command-Shift-Z 10 times to redo all the changes. Repeat steps 8–9 until either the app crashes or some of the 5 ParentItems go missing in the list (you may have to repeat them 10–20 times before the issue occurs). If you change line 43 of ContentView.swift to modelContext.autosaveEnabled = false and repeat the same steps above, the app will not crash and no ParentItems will go missing. Code ParentItem Model @Model final class ParentItem { var timestamp: Date @Relationship( deleteRule: .cascade, inverse: \ChildItem.parentItem ) var childItems: [ChildItem] = [] init(timestamp: Date) { self.timestamp = timestamp } } ChildItem Model @Model final class ChildItem { var index: Int var isModified = false var parentItem: ParentItem? init(index: Int) { self.index = index } } Creating, Inserting, and Linking ParentItem and ChildItem // Create and insert ParentItem let newParentItem = ParentItem( timestamp: Date() ) modelContext.insert(newParentItem) // Create and insert ChildItems var newChildItems: [ChildItem] = [] for index in 0..<Int.random(in: 2...8) { let newChildItem = ChildItem(index: index) newChildItems.append(newChildItem) modelContext.insert(newChildItem) } /* Establish relationship between ParentItem and ChildItems */ newParentItem.childItems = newChildItems Modifying ChildItem let firstChildItem = parentItem.childItems .sorted(by: { $0.index < $1.index }).first if let firstChildItem, !firstChildItem.isModified { firstChildItem.isModified = true }
Replies
2
Boosts
0
Views
214
Activity
2w
CKSyncEngine: Duplicate FetchedRecordZoneChanges & Sync Handling Questions
Hi everyone, I've recently implemented CKSyncEngine in my app, and I have two questions regarding its behavior: Duplicate FetchedRecordZoneChanges After Sending Changes: I’ve noticed that the engine sometimes receives a FetchedRecordZoneChanges event containing modifications and deletions that were just sent by the same device a few moments earlier. This event arrives after the SentRecordZoneChanges event, and both events share the same recordChangeTag, which results in double-handling the record. Is this expected behavior? I’d like to confirm if this is how CKSyncEngine works or if I might be overlooking something. Handling Initial Sync with a "Sync Screen": When a user opens the app for the first time and already has data stored in iCloud, I need to display a "Sync Screen" temporarily to prevent showing partial data or triggering abrupt, rapid UI changes. I’ve found that canceling current operations, then awaiting sendChanges() and fetchChanges() works well to ensure data is fully synced before dismissing the sync screen: displaySyncScreen = true await syncEngine.cancelOperations() try await syncEngine.sendChanges() try await syncEngine.fetchChanges() displaySyncScreen = false However, I’m unsure if canceling operations like this could lead to data loss or other issues. Is this a safe approach, or would you recommend a better strategy for handling this initial sync state?
Replies
2
Boosts
1
Views
842
Activity
2w
Production Mac app becomes progressively unusable in Issues workspace; Mac_Dev remains fast
The production macOS build is showing severe performance problems, while Mac_Dev performs normally. Observed behavior in production Mac build: Issue board scrolling becomes inconsistent or nearly unusable Changing an issue status in detail view is very slow Scrolling the status menu/options can be slow Typing in issue description/notes fields becomes sluggish Dragging issues between milestones/statuses on the board can lag badly Observed behavior in Mac_Dev: Board scrolling is smooth Status changes are immediate Typing in description fields is responsive Drag/drop between milestones works well Important comparison: Mac_Dev appears to run against an isolated local SwiftData store Production Mac app uses the normal CloudKit-backed store Because the same UI is fast in Mac_Dev, this does not look like a pure rendering problem Most likely cause is production store / CloudKit sync churn amplifying existing SwiftUI invalidation and save behavior Current hypothesis: The production app is saving or observing live Issue mutations too aggressively Detail view edits and some quick actions may be causing repeated saves / broad view invalidation Cloud-backed persistence likely makes the problem much worse than the isolated dev store The UI architecture may still need cleanup, but the production data lane is likely a major factor Any help in understanding how best to address this would be helpful.
Replies
2
Boosts
0
Views
168
Activity
3w
TestFlight build crashes from fetch descriptor
I have a FetchDescriptor that uses starts(with:) which works fine in debug builds but crashes in TestFlight and archive. For background information I'm using iCloud and model inheritance where the property being used in fetch descriptor is defined on the superclass, the fetch descriptor is for the subclass. Implementation: static func fetchDescriptor(nameStartingWith prefix: String) -> FetchDescriptor<ColorAsset> { let predicate = #Predicate<ColorAsset> { asset in asset.name.starts(with: prefix) } return FetchDescriptor<ColorAsset>(predicate: predicate) } @Model public class Asset: Identifiable { // MARK: - Properties var name: String = "" .... } @available(macOS 26.0, *) @Model public class ColorAsset: Asset { ... }
Replies
2
Boosts
0
Views
157
Activity
3w
SwiftData document-based app broken
Hello all Synopsis: document based SwiftData app breaks document handling after first save due to internal error saving the -shm file. Long: i am working on a small document based SwiftData app for macOS. The UI works well as long as the document was not saved. After saving the document and reopening it, I get an error consistently in console: BUG IN CLIENT OF libsqlite3.dylib: database integrity compromised by API violation: vnode unlinked while in use: /Users/vrunkel/Library/Containers/de.ecoobs.CurtailmentAnalyzer/Data/tmp/TemporaryItems/NSIRD_CurtailmentAnalyzer_mrXKMs/NewDocument/StoreContent-shm So somehow the -shm file is still referenced to NewDocument created when the app opens an untitled document and resides in the temporary folder. I have saved the document to my documents folder. After reopening and the above error deletion or addition of items crashes the app with a long backtrace to view updating: Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread. I am not creating any threads or do background work. If I do not save the document but work within the new untitled document no problems occur. Even closing the app and reopening the untitled new doc (happens automatically) all is fine. To rule out any influence of my existing view structure I have created the most simple test case - Xcode -> New Project -> macOS document based app configured to use SwiftData. Same behaviour. After saving a new document the addition/deletion of items causes the thread-induced crash and shows the error in console when opening the document. I am using latest versions of Xcode 15.0 and macOS 14.0 Any ideas? thx, volker
Replies
9
Boosts
2
Views
2.6k
Activity
3w
Core Data Migration Strategy: store relocation, schema changes and CloudKit adoption in a single release?
I am planning a Core Data migration for a macOS app targeting macOS 12 and later and I would appreciate guidance on structuring the rollout to minimise risk. Context The app currently uses a SQLite store located at: ~/Library/Containers/com.company.AppName/Data/Library/Application Support/AppName I want to: Relocate the persistent store to an app group container: ~/Library/Group Containers/group.com.company.AppName Perform schema migration, including: Renaming attributes Deleting attributes Using a custom NSEntityMigrationPolicy subclass Adopt iCloud sync using NSPersistentCloudKitContainer Potentially leverage staged migration (macOS 14+) Additionally, I intend to port the app to iOS, so the end state needs to support an app group container and CloudKit with the latest schema from the outset. Questions Store relocation vs schema migration Is it advisable to perform store relocation and schema migration in a single step, or should these be separate releases? If combined, are there pitfalls when moving the SQLite file and running a migration in the same launch cycle? Custom migration policy Any best practices for structuring NSEntityMigrationPolicy when also relocating the store? Should migration policies assume the store has already been moved, or handle both concerns? Staged migration (macOS 14+) Is staged migration worth adopting when still supporting macOS 12–13? Would you gate it conditionally, or avoid it entirely for consistency? CloudKit adoption Is introducing NSPersistentCloudKitContainer in the same release as the above migrations too risky? Are there known issues when enabling CloudKit immediately after a migration? Release strategy Would you recommend: A single release handling everything Two phases: (1) store & schema migration, (2) CloudKit Or three phases: store relocation → schema migration → CloudKit Goal I want a smooth, reliable transition without data loss or duplication, particularly for existing users with non-trivial datasets. Any insights, practical experience, or recommended sequencing strategies would be very helpful.
Replies
3
Boosts
0
Views
158
Activity
3w
CoreData + CloudKit -- Many-to-Many Relationship not Syncing
In an iOS App that uses CKShare I have a many-to-many relationship that does not consistently sync between the share's N participants. The relationship is between Group and Player as group.players and player.groups. As an example, given 3 group each with 4 players (aka 4:4:4), some devices show CoreData (it is NOT a UI issue) with 4:2:3 or 3:4:4. (A deletion of CoreData from a device, forcing a full re-sync from CloudKit, seems to populate the group:player relationships consistently; but obviously that is impractical to resolving the issue). How do I avoid these sync-from-CloudKit inconsistencies? Note: AI agents generally suggest adding a CoreData 'join' entity - such as 'GroupPlayer'. Is that THE fix?
Replies
1
Boosts
0
Views
112
Activity
3w
Best practice for centralizing SwiftData query logic and actions in an @Observable manager?
I'm building a SwiftUI app with SwiftData and want to centralize both query logic and related actions in a manager class. For example, let's say I have a reading app where I need to track the currently reading book across multiple views. What I want to achieve: @Observable class ReadingManager { let modelContext: ModelContext // Ideally, I'd love to do this: @Query(filter: #Predicate<Book> { $0.isCurrentlyReading }) var currentBooks: [Book] // ❌ But @Query doesn't work here var currentBook: Book? { currentBooks.first } func startReading(_ book: Book) { // Stop current book if any if let current = currentBook { current.isCurrentlyReading = false } book.isCurrentlyReading = true try? modelContext.save() } func stopReading() { currentBook?.isCurrentlyReading = false try? modelContext.save() } } // Then use it cleanly in any view: struct BookRow: View { @Environment(ReadingManager.self) var manager let book: Book var body: some View { Text(book.title) Button("Start Reading") { manager.startReading(book) } if manager.currentBook == book { Text("Currently Reading") } } } The problem is @Query only works in SwiftUI views. Without the manager, I'd need to duplicate the same query in every view just to call these common actions. Is there a recommended pattern for this? Or should I just accept query duplication across views as the intended SwiftUI/SwiftData approach?
Replies
3
Boosts
0
Views
596
Activity
4w
Fatal error on rollback after delete
I encountered an error when trying to rollback context after deleting some model with multiple one-to-many relationships when encountered a problem later in a deleting method and before saving the changes. Something like this: do { // Fetch model modelContext.delete(model) // Do some async work that potentially throws try modelContext.save() } catch { modelContext.rollback() } When relationship is empty - the parent has no children - I can safely delete and rollback with no issues. However, when there is even one child when I call even this code: modelContext.delete(someModel) modelContext.rollback() I'm getting a fatal error: SwiftData/ModelSnapshot.swift:46: Fatal error: Unexpected backing data for snapshot creation: SwiftData._FullFutureBackingData<ChildModel> I use ModelContext from within the ModelActor but using mainContext changes nothing. My ModelContainer is quite simple and problem occurs on both in-memory and persistent storage, with or without CloudKit database being enabled. I can isolate the issue in test environment, so the model that's being deleted (or any other) is not being accessed by any other part of the application. However, problem looks the same in the real app. I also changed the target version of iOS from 18.0 to 26.0, but to no avail. My models look kind of like this: @Model final class ParentModel { var name: String @Relationship(deleteRule: .cascade, inverse: \ChildModel.parent) var children: [ChildModel]? init(name: String) { self.name = name } } @Model final class ChildModel { var name: String @Relationship(deleteRule: .nullify) var parent: ParentModel? init(name: String) { self.name = name } } I tried many approaches that didn't help: Fetching all children (via fetch) just to "populate" the context Accessing all children on parent model (via let _ = parentModel.children?.count) Deleting all children reading models from parent: for child in parentModel.children ?? [] { modelContext.delete(child) } Deleting all children like this: let parentPersistentModelID = parentModel.persistentModelID modelContext.delete(model: ChildModel.self, where: #Predicate { $0.parent.persistentModelID == parentPersistentModelID }, includeSubclasses: true) Removing @Relationship(deleteRule: .nullify) from ChildModel relationship definition I found 2 solution for the problem: To manually fetch and delete all children prior to deleting parent: let parentPersistentModelID = parentModel.persistentModelID for child in try modelContext.fetch(FetchDescriptor<ChildModel>(predicate: #Predicate { $0.parent.persistentModelID == parentPersistentModelID })) { modelContext.delete(child) } modelContext.delete(parentModel) Trying to run my code in child context (let childContext = ModelContext(modelContext.container)) All that sounds to me like a problem deep inside Swift Data itself. The first solution I found, fetching potentially hundreds of child models just to delete them in case I might need to rollback changes on some error, sounds like awful waste of resources to me. The second one however seems to work fine has that drawback that I can't fully test my code. Right now I can wrap the context (literally creating class that holds ModelContext and calls its methods) and in tests for throwing methods force them to throw. By creating scratch ModelContext I loose that possibility. What might be the real issue here? Am I missing something?
Replies
2
Boosts
0
Views
207
Activity
4w