Error happened when I return back from offline mode and turn on the wifi, Also a crash happened if I restarted the data store again
Describe the bug
When using DataStore, after configuring the Amplify and start syncing, try to turn off the wifi, then turn it on again, an error will be displayed in XCode logs, if you then forced syncing your DataStore by stopping the DataStore and started it again a crash will happen.
Steps To Reproduce
1. Open your app normally
2. wait until the DataStore and Amplify to be configured and synced
3. turn off the wifi
4. turn it on again
5. An error will be logged that there is an error caused by connection
6. force syncing the DataStore (stop DataStore, then start DataStore)
7. A crash will happen in Storage Engine
Amplify.DataStore.stop { _ in
Amplify.DataStore.start { _ in
}
}
Expected behavior
To sync data normally.
Amplify Framework Version
1.28.0
Amplify Categories
DataStore
Dependency manager
Cocoapods
Swift version
5.0
CLI version
Not Installed
Xcode version
13.3.1
Relevant log output
Error Log:
User receives a network connection status: true
************************************** HubPayload(eventName: "DataStore.networkStatus", context: nil, data: Optional(AmplifyPlugins.NetworkStatusEvent(active: true)))
2022-08-17 20:30:01.038161+0300 TeamHub[9288:290017] [RealtimeConnectionProvider] Realtime connection is stale, disconnecting.
2022-08-17 20:30:01.039196+0300 TeamHub[9288:290017] ConnectionProviderError.connection
2022-08-17 20:30:01.039787+0300 TeamHub[9288:290017] ConnectionProviderError.connection
2022-08-17 20:30:01.042814+0300 TeamHub[9288:290017] ConnectionProviderError.connection
2022-08-17 20:30:01.055788+0300 TeamHub[9288:290070] [AWSModelReconciliationQueue] receiveCompletion: error: DataStoreError: Subscription item event failed with error
Caused by:
APIError: Subscription item event failed with error
Caused by:
connection
2022-08-17 20:30:01.060776+0300 TeamHub[9288:290017] [AWSDataStorePlugin] StorageEngine completed with error: DataStoreError: Subscription item event failed with error
Caused by:
DataStoreError: Subscription item event failed with error
Caused by:
APIError: Subscription item event failed with error
Caused by:
connection
------------------------------------------------------------------------------------------------
Crash stack trace:
* thread #1, queue = 'AWSDataStorePlugin.storageEngineInitQueue', stop reason = EXC_BREAKPOINT (code=1, subcode=0x102bc5b50)
frame #0: 0x0000000102bc5b50 libdispatch.dylib`__DISPATCH_WAIT_FOR_QUEUE__ + 456
frame #1: 0x0000000102bc551c libdispatch.dylib`_dispatch_sync_f_slow + 172
frame #2: 0x0000000199cede18 libswiftDispatch.dylib`merged implicit closure #2 (() -> ()) -> () in implicit closure #1 (__C.OS_dispatch_queue) -> (() -> ()) -> () in __C.OS_dispatch_queue.sync<τ_0_0>(execute: () throws -> τ_0_0) throws -> τ_0_0 + 152
frame #3: 0x0000000199ced0ac libswiftDispatch.dylib`partial apply forwarder for implicit closure #2 (() -> ()) -> () in implicit closure #1 (__C.OS_dispatch_queue) -> (() -> ()) -> () in __C.OS_dispatch_queue.sync<τ_0_0>(execute: () throws -> τ_0_0) throws -> τ_0_0 + 40
frame #4: 0x0000000199cedbb0 libswiftDispatch.dylib`__C.OS_dispatch_queue._syncHelper<τ_0_0>(fn: (() -> ()) -> (), execute: () throws -> τ_0_0, rescue: (Swift.Error) throws -> τ_0_0) throws -> τ_0_0 + 256
frame #5: 0x0000000199ced140 libswiftDispatch.dylib`__C.OS_dispatch_queue.sync<τ_0_0>(execute: () throws -> τ_0_0) throws -> τ_0_0 + 140
* frame #6: 0x00000001039dd5cc AmplifyPlugins`AWSDataStorePlugin.initStorageEngine(self=0x00000001040519f0) at AWSDataStorePlugin.swift:114:32
frame #7: 0x00000001039de4c0 AmplifyPlugins`AWSDataStorePlugin.initStorageEngineAndStartSync(completion=0x00000001039e8b40 AmplifyPlugins`partial apply forwarder for closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in AmplifyPlugins.AWSDataStorePlugin.start(completion: (Swift.Result<(), Amplify.DataStoreError>) -> ()) -> () at <compiler-generated>, self=0x00000001040519f0) at AWSDataStorePlugin.swift:146:16
frame #8: 0x00000001039e8a88 AmplifyPlugins`AWSDataStorePlugin.start(completion=0x00000001004d8a78 TeamHub`partial apply forwarder for closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in TeamHub.AmplifyManager.syncDataStore(completion: () -> ()) -> () at <compiler-generated>, self=0x00000001040519f0) at AWSDataStorePlugin+DataStoreBaseBehavior.swift:268:9
frame #9: 0x00000001039eab84 AmplifyPlugins`protocol witness for DataStoreBaseBehavior.start(completion:) in conformance AWSDataStorePlugin at <compiler-generated>:0
frame #10: 0x0000000102e4ea20 Amplify`DataStoreCategory.start(completion=0x00000001004d8a78 TeamHub`partial apply forwarder for closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in TeamHub.AmplifyManager.syncDataStore(completion: () -> ()) -> () at <compiler-generated>, self=0x000000028343b270) at DataStoreCategory+Behavior.swift:78:16
frame #11: 0x00000001004d61ec TeamHub`closure #1 in AmplifyManager.syncDataStore(_0=(success = () @ 0x000000016fa38930), completion=0x000000010044a7f0 TeamHub`closure #1 () -> () in TeamHub.EmployeeLoginViewController.didClickLoginButton() -> () at EmployeeLoginViewController.swift:278:9) at AmplifyManager.swift:155:31
frame #12: 0x00000001039e91f0 AmplifyPlugins`closure #1 in AWSDataStorePlugin.stop(self=0x00000001040519f0, completion=0x00000001004d6248 TeamHub`partial apply forwarder for closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in TeamHub.AmplifyManager.syncDataStore(completion: () -> ()) -> () at <compiler-generated>) at AWSDataStorePlugin+DataStoreBaseBehavior.swift:285:17
frame #13: 0x00000001039e96b8 AmplifyPlugins`thunk for @callee_guaranteed () -> () at <compiler-generated>:0
frame #14: 0x00000001039e9718 AmplifyPlugins`thunk for @escaping @callee_guaranteed () -> () at <compiler-generated>:0
frame #15: 0x0000000102bb5fc8 libdispatch.dylib`_dispatch_client_callout + 16
frame #16: 0x0000000102bc5790 libdispatch.dylib`_dispatch_lane_barrier_sync_invoke_and_complete + 116
frame #17: 0x00000001039e8cd0 AmplifyPlugins`AWSDataStorePlugin.stop(completion=0x00000001004d6248 TeamHub`partial apply forwarder for closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in TeamHub.AmplifyManager.syncDataStore(completion: () -> ()) -> () at <compiler-generated>, self=0x00000001040519f0) at AWSDataStorePlugin+DataStoreBaseBehavior.swift:274:32
frame #18: 0x00000001039eaba4 AmplifyPlugins`protocol witness for DataStoreBaseBehavior.stop(completion:) in conformance AWSDataStorePlugin at <compiler-generated>:0
frame #19: 0x0000000102e4eab0 Amplify`DataStoreCategory.stop(completion=0x00000001004d6248 TeamHub`partial apply forwarder for closure #1 (Swift.Result<(), Amplify.DataStoreError>) -> () in TeamHub.AmplifyManager.syncDataStore(completion: () -> ()) -> () at <compiler-generated>, self=0x000000028343b270) at DataStoreCategory+Behavior.swift:82:16
frame #20: 0x00000001004d6100 TeamHub`AmplifyManager.syncDataStore(completion=0x000000010044a7f0 TeamHub`closure #1 () -> () in TeamHub.EmployeeLoginViewController.didClickLoginButton() -> () at EmployeeLoginViewController.swift:278:9, self=0x0000000282f2b740) at AmplifyManager.swift:154:27
frame #21: 0x000000010044a7d8 TeamHub`EmployeeLoginViewController.didClickLoginButton(self=0x0000000103811650) at EmployeeLoginViewController.swift:276:31
frame #22: 0x000000010044a818 TeamHub`@objc EmployeeLoginViewController.didClickLoginButton() at <compiler-generated>:0
frame #23: 0x0000000183e9c0b4 UIKitCore`-[UIApplication sendAction:to:from:forEvent:] + 96
frame #24: 0x0000000183fbb20c UIKitCore`-[UIControl sendAction:to:forEvent:] + 124
frame #25: 0x0000000183d5143c UIKitCore`-[UIControl _sendActionsForEvents:withEvent:] + 352
frame #26: 0x0000000183de8318 UIKitCore`-[UIButton _sendActionsForEvents:withEvent:] + 156
frame #27: 0x000000018405feb0 UIKitCore`-[UIControl touchesEnded:withEvent:] + 516
frame #28: 0x0000000183b65e74 UIKitCore`-[UIWindow _sendTouchesForEvent:] + 1228
frame #29: 0x0000000183b95994 UIKitCore`-[UIWindow sendEvent:] + 4372
frame #30: 0x0000000183d36504 UIKitCore`-[UIApplication sendEvent:] + 892
frame #31: 0x0000000183b6a974 UIKitCore`__dispatchPreprocessedEventFromEventQueue + 8148
frame #32: 0x0000000183b5f838 UIKitCore`__processEventQueue + 6544
frame #33: 0x0000000183b64c54 UIKitCore`__eventFetcherSourceCallback + 168
frame #34: 0x000000018177e4ec CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
frame #35: 0x000000018178e61c CoreFoundation`__CFRunLoopDoSource0 + 204
frame #36: 0x00000001816d0824 CoreFoundation`__CFRunLoopDoSources0 + 256
frame #37: 0x00000001816d5ef8 CoreFoundation`__CFRunLoopRun + 768
frame #38: 0x00000001816e9240 CoreFoundation`CFRunLoopRunSpecific + 572
frame #39: 0x00000001a1ff3988 GraphicsServices`GSEventRunModal + 160
frame #40: 0x0000000183ee941c UIKitCore`-[UIApplication _run] + 1080
frame #41: 0x0000000183c82b88 UIKitCore`UIApplicationMain + 336
frame #42: 0x00000001004b545c TeamHub`main at AppDelegate.swift:15:7
frame #43: 0x000000010170c3d0 dyld`start + 444
Is this a regression?
Yes
Regression additional context
No response
Device
iPad 5th generation
iOS Version
15.5
Specific to simulators
No response
Additional context
No response
Thanks for reporting this. We're tracking a related issue here.
Thanks for reporting this. We're tracking a related issue here.
Ok thank you, but also there is another part for this issue that it causing a crash if you stopped and started the DataStore again.
when this error appeared "DataStoreError: Subscription item event failed with error Caused by: APIError: Subscription item event failed with error Caused by: connection"
try to execute this code below, the app will crash
Amplify.DataStore.stop { _ in
Amplify.DataStore.start { _ in
}
}
Hello @ameter, I need to ask a question, are there any way to know that the DataStore is stopped? like a boolean flag or something?
or a way to know that the above failure happened?
Unfortunately there is not a good event to know that DataStore has stopped in this case. However, calling DataStore stop before start here is unnecessary. Calling start alone should recover from this situation. In addition, any DataStore operation (save, query, delete, etc.) will also start DataStore if it is not already started. The crash is still unexpected behavior so thank you for reporting that.
I see based on the logs that you provided that you are attempting to use the networkStatus hub event as a work around. Unfortunately this will not work because this event is dispatched before DataStore is stopped due to the logic in https://github.com/aws-amplify/amplify-ios/pull/1901. This behavior is intentional to fix a separate issue, however it has unintended side effects here.
All this to say is that this issue will break real time subscriptions, but the remainder of DataStore should function as expected.
We don't have an ETA on the fix at this time.
@dpilch Thank you for your answer, Yes I know that starting the DataStore will avoid the crash, but we have a use case that we are providing the user a force sync button, he can click on it to force sync everything from AppSync, so if the user turn on the wifi and clicked this button the app will crash, because this button implementation is to stop the DataStore and start it again.
force sync button implementation:
Amplify.DataStore.stop { _ in
Amplify.DataStore.start { _ in
}
}
Ah, I understand. I would say for the time being the solution would be to wrap the stop with another start. This isn't the prettiest solution, but will be fine because DataStore start is a no-op when already started.
Amplify.DataStore.start { _ in
Amplify.DataStore.stop { _ in
Amplify.DataStore.start { _ in
}
}
}
We will continue to look into the fix for crash as well as the incorrect stopping outlined in https://github.com/aws-amplify/amplify-ios/issues/2152
@dpilch Yes I did that recently to avoid the crash and to maintain the app to work normally for now. Thank you for your collaboration 🙏🏻
Hi @medhatIbsais-Harri, thanks for reporting this issue. the following code snippet should not crash the app
Amplify.DataStore.stop { _ in
Amplify.DataStore.start { _ in
}
}
Glad @dpilch's workaround is working for you. we'll keep this issue open until we have a fix for the above code snippet does not crash an app
Hi @lawmicha, thank you for your collaboration, but the code snippet below will crash the app, the idea if you request Amplify.DataStore.stop while it’s already stopped, this will crash the app, so that I used the workaround which is to request DataStore.start, then DataStore.Stop, then DataStore.start again, so that I avoid the crash.
Amplify.DataStore.stop { _ in
Amplify.DataStore.start { _ in
}
}
We were able to reproduce the crash and the issue is that start is trying to perform the work synchronously on the same DispatchQueue that stop is currently using. This causes a deadlock because start waits for the queue but is never able to acquire it, since start is called in the completion closure of stop. To get around this, you can dispatch the call to start on a separate thread, for example
Amplify.DataStore.stop { _ in
DispatchQueue.global(qos: .background).async {
Amplify.DataStore.start { _ in
}
}
}
We have the PR in progress to fix so that you do not have to do the workaround above: https://github.com/aws-amplify/amplify-swift/pull/2517
@lawmicha thank you, we did another workaround and its working for now, we will wait for your fix
Hi @medhatIbsais-Harri you should be able to upgrade to version 1.28.3, we've released the fix for this issue. Please let us know if you continue to experience any issues. 🙏
Thank you @chrisbonifacio
Hello @chrisbonifacio, I'm still experiencing this issue on Amplify (1.28.3)
the crash problem is resolved but still receiving this error logs when I return back from offline mode to online mode
2022-11-30 16:16:19.507663+0200 TeamHub Pro[2793:73400] [RealtimeConnectionProvider] Realtime connection is stale, disconnecting.
2022-11-30 16:16:19.508623+0200 TeamHub Pro[2793:73400] ConnectionProviderError.connection
2022-11-30 16:16:19.509441+0200 TeamHub Pro[2793:73400] ConnectionProviderError.connection
2022-11-30 16:16:19.510948+0200 TeamHub Pro[2793:73400] ConnectionProviderError.connection
2022-11-30 16:16:19.519136+0200 TeamHub Pro[2793:73451] [AWSModelReconciliationQueue] [InitializeSubscription.3] AWSModelReconciliationQueue receiveCompletion: error: DataStoreError: Subscription item event failed with error
Caused by:
APIError: Subscription item event failed with error
Caused by:
connection
2022-11-30 16:16:19.522977+0200 TeamHub Pro[2793:73400] [AWSDataStorePlugin] StorageEngine completed with error: DataStoreError: Subscription item event failed with error
Caused by:
DataStoreError: Subscription item event failed with error
Caused by:
APIError: Subscription item event failed with error
Caused by:
connection
Hello @chrisbonifacio, any updates here?
Hello @chrisbonifacio @lawmicha, any updates here?