You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, thanks for SQLiteData. We use SyncEngine at 1.12.0 (164bb5f) in an iOS app with a macOS menu-bar companion (LSUIElement), syncing the private and shared databases. Two things we'd value your view on.
1. A server-confirmed change that fetchChanges() didn't discover in our captured runs
On macOS 26.6.2 (Basket Case 2.5.4 build 1, a TestFlight build), a private-database change saved while the Mac app wasn't running was confirmed present on the server. It wasn't fetched. Neither SyncEngine.fetchChanges() nor CKSyncEngine's automatic start-up sync made a request; each logged:
<CKSyncEngine Private> no zone IDs needing to be fetched, not fetching changes
The change arrived only with the next push to that database, 8 h 51 m later.
Steps, reproduced once; we haven't established how often it happens:
initial sync completed and engine state persisted
Mac app quit
change made on another device, confirmed on the server
Mac app relaunched
explicit fetchChanges()
Our reading is that this is CKSyncEngine behaviour rather than SyncEngine's: fetchChanges() passes straight through to both engines. For comparison:
On iOS 27.0, CKSyncEngine's own foreground handler recovered a missed change (received appForegroundNotificationName → setting needs to fetch database changes 1).
An explicit fetch during an iOS background launch was a no-op too.
On the macOS agent, opening the panel (with NSApp.activate()) showed no foreground handling.
Caveats: one run each; the platforms run different OS versions; we didn't verify that the Mac app actually became active; and our reproduction without SQLiteData is still pending.
We're reporting this to Apple as well. Our questions for you:
Have you seen this, or is it known?
Is there a supported way, through SyncEngine or otherwise, to make the engines fetch database changes on demand, e.g. when a macOS agent's panel opens? CKSyncEngine.State doesn't seem to expose a setter for this, and SyncEngine keeps its engines package-scoped.
2. Per-zone fetch errors aren't visible in release builds
In handleEvent, .didFetchRecordZoneChanges is matched without binding its error, and events are logged only under #if DEBUG. fetchChanges() throws only when the whole operation fails. So in a release/TestFlight build, a failed per-zone fetch leaves no trace in the app's own logs; it shows up only with Apple's CloudKit logging profile installed. During our investigation that made "no failure logged" look like success.
Would you be open to exposing per-zone fetch errors in release builds, through whatever logging or callback API you prefer? We'd be glad to contribute a PR if that helps.
On macOS 26.6.2 (Basket Case 2.5.4 build 1, a TestFlight build), a private-database change saved while the Mac app wasn't running was confirmed present on the server. It wasn't fetched. Neither SyncEngine.fetchChanges() nor CKSyncEngine's automatic start-up sync made a request; each logged:
I would be very surprised if the CKSyncEngine did not grab the newest records when it starts up fresh. I would triple check that you are in fact seeing that. And in general I find that Mac apps only get newest records when the app starts fresh, and when backgrounding+foregrounding the app. I have not had a lot of luck with push notifications working to make Mac apps sync live while the app is open.
5. explicit fetchChanges()
From our experience, fetchChanges on CKSyncEngine does not do anything. Seems to be an issue with CKSyncEngine and a feedback should be filed with Apple.
Thanks, @mbrandonw, that's really helpful, and it matches what we saw with fetchChanges(). We've filed it with Apple as FB24904092, with the captures attached.
On start-up, I've re-checked what we have. In our one captured Mac relaunch, the engine's automatic sync logged this while a server-confirmed change was pending:
<CKSyncEngine Private> performing an automatically scheduled sync
<CKSyncEngine Private> no zone IDs needing to be fetched, not fetching changes
That relaunch had persisted engine state. When you say "starts up fresh", do you mean without a saved state serialization? We're setting up an isolated reproduction without SQLiteData, and we'll test both cases separately.
On the Mac, "backgrounding + foregrounding" may be the key for us. Our Mac companion is a menu-bar-only app (LSUIElement), so it never really backgrounds or foregrounds. On iOS we can see the engine's own handler doing the catch-up:
received appForegroundNotificationName notification
setting needs to fetch database changes 1
When the Mac panel opens, though, we call NSApp.activate() and nothing like that shows up in the log. Do you know what the Mac engine actually listens for, and have you seen the catch-up work for an agent/menu-bar app?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Hi, thanks for SQLiteData. We use
SyncEngineat 1.12.0 (164bb5f) in an iOS app with a macOS menu-bar companion (LSUIElement), syncing the private and shared databases. Two things we'd value your view on.1. A server-confirmed change that fetchChanges() didn't discover in our captured runs
On macOS 26.6.2 (Basket Case 2.5.4 build 1, a TestFlight build), a private-database change saved while the Mac app wasn't running was confirmed present on the server. It wasn't fetched. Neither
SyncEngine.fetchChanges()nor CKSyncEngine's automatic start-up sync made a request; each logged:The change arrived only with the next push to that database, 8 h 51 m later.
Steps, reproduced once; we haven't established how often it happens:
fetchChanges()Our reading is that this is CKSyncEngine behaviour rather than SyncEngine's:
fetchChanges()passes straight through to both engines. For comparison:received appForegroundNotificationName→setting needs to fetch database changes 1).NSApp.activate()) showed no foreground handling.Caveats: one run each; the platforms run different OS versions; we didn't verify that the Mac app actually became active; and our reproduction without SQLiteData is still pending.
We're reporting this to Apple as well. Our questions for you:
SyncEngineor otherwise, to make the engines fetch database changes on demand, e.g. when a macOS agent's panel opens?CKSyncEngine.Statedoesn't seem to expose a setter for this, andSyncEnginekeeps its enginespackage-scoped.2. Per-zone fetch errors aren't visible in release builds
In
handleEvent,.didFetchRecordZoneChangesis matched without binding itserror, and events are logged only under#if DEBUG.fetchChanges()throws only when the whole operation fails. So in a release/TestFlight build, a failed per-zone fetch leaves no trace in the app's own logs; it shows up only with Apple's CloudKit logging profile installed. During our investigation that made "no failure logged" look like success.Would you be open to exposing per-zone fetch errors in release builds, through whatever logging or callback API you prefer? We'd be glad to contribute a PR if that helps.
All reactions