Skip to content

IOS Background reopen: @firebase/firestore: Firestore (7.6.2): FIRESTORE (7.6.2) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction@[native code] #2581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Sroose opened this issue Jan 30, 2020 · 19 comments
Assignees

Comments

@Sroose
Copy link

Sroose commented Jan 30, 2020

Describe your environment

  • Operating System version: IOS 13.3
  • Browser version: Mobile Safari UI/WKWebView 13.3
  • Firebase SDK version: 7.6.2
  • Firebase Product: database (firestore)

Describe the problem

Steps to reproduce:

Ionic cordova app using Firestore. Works very well under normal situations.
When opening through notification and it's a cold app start, also no problems.
But only when the app is in the background and reopened through a notification tap, firebase will throw a lot of errors and stop working:

@firebase/firestore: Firestore (7.6.2): FIRESTORE (7.6.2) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction@[native code]

Relevant Code:

(Cannot reproduce this on stackblitz as it is on device.)
Simplified use:

constructor(public storage: AngularFireStorage,
                public auth: AuthService,
                private afs: AngularFirestore,
                private fns: AngularFireFunctions) {
}

private loadData() {
...
this.itemList= this.afs.collection('users').doc(uid).collection<ItemList>('items').valueChanges({ idField: 'item' });
...
}
<ion-list *ngIf="itemList| async as item; else loadingOrError">
@Sroose
Copy link
Author

Sroose commented Jan 30, 2020

@rommelpe
Copy link

Hi @Sroose thanks for reporting this issue. While I'm trying to reproduce this on my end, it would be great if you can provide a working repro that we can run locally to speed up the investigation. Thanks!

@schmidt-sebastian
Copy link
Contributor

@Sroose We have seen similar issues with our iOS SDK. Essentially, what can happen is that iOS locks the file system when an app is backgrounded. If the database is accessed when the file system is locked, the operation will fail.

We already retry transactions when they fail (

), but this might not help if the app stays backgrounded. We can likely be smarter about this - but it would help us if you could provide a reproduction (as suggested above) or provide logging. Logs will help me determine if we are already retrying and if we should retry until the file system lock is released.

In the Web SDK, logging can be turned on via setLogLevel().

@Pitouli
Copy link

Pitouli commented Jan 31, 2020

Hello,

I have the same issue.

My app has the following features: it's a PWA, using Framework7 and using Firebase for Auth and DB (Firestore).

When I pin it to my dashboard on iOS, if I open the app, then switch to another app, the switch back to it, Firestore crashes with the following error: FIRESTORE (7.7.0) INTERNAL ASSERTION FAILED: AsyncQueue is already failed. Then, the only solution is to kill the app, and restart it. And since it's systematic, that means you always have to kill the app before using it.

Some of my observations:

  • No issue with Android (you can close, reopen, no bug) or on a browser
  • The issue started with iOS 13 (before iOS 13, the PWAs were killed 5 seconds after being closed so the "reopening bug" didn't appeared)
  • No issue if the app is used directly in Safari (you can switch tabs, switch from Safari to another app, come back: it will not crash)

I already be involved in the following threads, but they have not corrected my issue:

I decided to reproduce the bug with the smallest app I could.

Simple PWA / Vue.js / Vuex / Firestore / Vuexfire -> RANDOMLY FAIL
I made a PWA Vue App, with Firestore and Vuexfire.
I started from this template: https://github.com/erisu/pwa-vue-app-1/tree/pwa
I forked and added the Firestore/Vuexfire part: https://github.com/Pitouli/pwa-vue-app-1
I published it on the web: https://debug-and-test-env.firebaseapp.com/
The bug is very hard to reproduce with certainty. Sometimes it bugs, sometimes not.

Framework7 PWA / Vue.js / Vuex / Firestore / Vuexfire -> FAIL
I started with the Framework7 CLI
Then I simply added the same Firestore/Vuexfire part than in the other: https://github.com/Pitouli/debug-ios-vuexfire
I published it on the web: https://debug-ios-vuexfire.firebaseapp.com/
This time, it fails almost every time.

Since I sometimes observes the bug in the first one, it's probably not relative to Framework7. It's possible that Framework7 make the app bigger, so iOS wait less time before killing some of the parts.

@schmidt-sebastian
Copy link
Contributor

@Pitouli Thanks for the detailed response!

#1670 is an iOS bug that we cannot work around. #2232 should have been addressed and resolve issues for apps that are in the foreground.

I suspect that you are also seeing issues with a locked file system on iOS. If you have the original error message (the part after "AsyncQueue is already failed") that would help us narrow it down.

In general, I think we can probably be smarter about our transaction retries and delay retries until the app comes back in the foreground. I will talk to my team about this.

@Sroose
Copy link
Author

Sroose commented Jan 31, 2020

FYI, we have added a piece of code that detects when the app will go to background and at that point unsubscribe from the Firestore objects, and resubscribe when coming back from background. So far this seems to be a working workaround for the issue. UPDATE: we still experience issues even with this 'fix'

Note that I do not consider this a solution but it might be helpful in further analyses and also be useful to others:

// @ionic/angular Platform
this.platform.pause.subscribe(() => {
  // unsubscribe here
});
this.platform.resume.subscribe(() => {
  // resubscribe here
});

@Pitouli
Copy link

Pitouli commented Jan 31, 2020

@schmidt-sebastian : a screnshot and a copy paste
Capture d’écran 2020-02-01 à 00 38 23

[Error] Failed to load resource: La connexion réseau a été perdue. (channel, line 0) [Error] Failed to load resource: La connexion réseau a été perdue. (channel, line 0) [Error] Failed to load resource: La connexion réseau a été perdue. (channel, line 0) [Error] [2020-01-31T23:36:35.388Z] @firebase/firestore: – "Firestore (7.7.0): INTERNAL UNHANDLED ERROR: " (1) transaction(fonction anonyme) — index.cjs.js:3468(fonction anonyme) — index.cjs.js:3322(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:84:144(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:8809(fonction anonyme) — index.cjs.js:11190(fonction anonyme) — index.cjs.js:18511(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:18462:90(fonction anonyme) — tslib.es6.js:99o — tslib.es6.js:70promiseReactionJob s (app.js:2:151831) (fonction anonyme) (app.js:2:153197) v (app.js:2:156023) (fonction anonyme) (app.js:2:171917) promiseReactionJob [Error] [2020-01-31T23:36:35.391Z] @firebase/firestore: (1) Firestore (7.7.0): FIRESTORE (7.7.0) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction(fonction anonyme) — index.cjs.js:3468(fonction anonyme) — index.cjs.js:3322(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:84:144(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:8809(fonction anonyme) — index.cjs.js:11190(fonction anonyme) — index.cjs.js:18511(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:18462:90(fonction anonyme) — tslib.es6.js:99o — tslib.es6.js:70promiseReactionJob s (app.js:2:151831) (fonction anonyme) (app.js:2:153197) v (app.js:2:156023) b (app.js:2:156264) (fonction anonyme) (app.js:2:172496) (fonction anonyme) (app.js:2:171631) (fonction anonyme) (app.js:2:171023) (fonction anonyme) (app.js:2:265142) [Error] (1) b (app.js:2:156280) (fonction anonyme) (app.js:2:172496) (fonction anonyme) (app.js:2:171631) (fonction anonyme) (app.js:2:171023) (fonction anonyme) (app.js:2:265142) [Error] Failed to load resource: WebKit a rencontré une erreur interne (channel, line 0) [Error] Failed to load resource: WebKit a rencontré une erreur interne (channel, line 0) [Error] Unhandled Promise Rejection: InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing. (fonction anonyme) rejectPromise promiseReactionJob [Error] InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing. (fonction anonyme) (app.js:2:172027) [Error] [2020-01-31T23:36:39.331Z] @firebase/firestore: (1) Firestore (7.7.0): FIRESTORE (7.7.0) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction(fonction anonyme) — index.cjs.js:3468(fonction anonyme) — index.cjs.js:3322(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:84:144(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:8809(fonction anonyme) — index.cjs.js:11190(fonction anonyme) — index.cjs.js:18511(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:18462:90(fonction anonyme) — tslib.es6.js:99o — tslib.es6.js:70promiseReactionJob s (app.js:2:151831) (fonction anonyme) (app.js:2:153197) v (app.js:2:156023) b (app.js:2:156264) (fonction anonyme) (app.js:2:172496) (fonction anonyme) (app.js:2:171631) (fonction anonyme) (app.js:2:171023) (fonction anonyme) (app.js:2:170373) [Error] (1) b (app.js:2:156280) (fonction anonyme) (app.js:2:172496) (fonction anonyme) (app.js:2:171631) (fonction anonyme) (app.js:2:171023) (fonction anonyme) (app.js:2:170373) [Error] [2020-01-31T23:36:45.740Z] @firebase/firestore: (1) Firestore (7.7.0): FIRESTORE (7.7.0) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction(fonction anonyme) — index.cjs.js:3468(fonction anonyme) — index.cjs.js:3322(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:84:144(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:8809(fonction anonyme) — index.cjs.js:11190(fonction anonyme) — index.cjs.js:18511(fonction anonyme) — tslib.es6.js:99(fonction anonyme) — tslib.es6.js:73initializePromisePromiseu — tslib.es6.js:69(fonction anonyme) — index.cjs.js:18462:90(fonction anonyme) — tslib.es6.js:99o — tslib.es6.js:70promiseReactionJob s (app.js:2:151831) (fonction anonyme) (app.js:2:153197) v (app.js:2:156023) b (app.js:2:156264) (fonction anonyme) (app.js:2:172496) (fonction anonyme) (app.js:2:171631) (fonction anonyme) (app.js:2:171023) (fonction anonyme) (app.js:2:430765) (fonction anonyme) (app.js:2:482247) (fonction anonyme) (app.js:2:115235) (fonction anonyme) (app.js:2:116971) addMessage (app.js:2:1217910) addMessage He (app.js:2:12397) He (app.js:2:12397) (fonction anonyme) (app.js:2:35293) (fonction anonyme) (app.js:2:1029369) forEach Gr (app.js:2:1029342) dispatchEvent (app.js:2:1084798) dispatchEvent onClick (app.js:2:1084669) onClick bound onClick [Error] Error: FIRESTORE (7.7.0) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction@[native code] https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:193871 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:192242 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:123935 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:123421 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:122977 initializePromise@[native code] Promise@[native code] u@https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:122766 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:263300 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:298977 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:407054 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:123935 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:122977 initializePromise@[native code] Promise@[native code] u@https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:122766 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:406304 https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:123935 o@https://debug-ios-vuexfire.firebaseapp.com/js/app.js:2:122808 promiseReactionJob@[native code] — index.cjs.js:156 Ge (app.js:2:12767) We (app.js:2:12680) Ue (app.js:2:12330) He (app.js:2:12532) He (app.js:2:12397) (fonction anonyme) (app.js:2:35293) (fonction anonyme) (app.js:2:1029369) forEach Gr (app.js:2:1029342) dispatchEvent (app.js:2:1084798) dispatchEvent onClick (app.js:2:1084669) onClick bound onClick

@nVitius
Copy link

nVitius commented Feb 5, 2020

Is there a separate ticket for handling this issue on other platforms? I've had it pop up in production on Windows 10 using Chrome (Firestore 7.6.2).

@AoDev
Copy link

AoDev commented Feb 6, 2020

We are affected as well and found this issue in stackoverflow.

@schmidt-sebastian
Copy link
Contributor

We had a discussion internally and found a potential strategy to mitigate these issue. This will require some thought and an implementation plan. Please do bear with us as we see this through.

As a workaround, I would recommend not using the SDK while the app is in the background. You may also have to call disableNetwork() to prevent network traffic from writing to IndexedDB.

@Sroose
Copy link
Author

Sroose commented Feb 8, 2020

Hi @schmidt-sebastian
Some extra information that might be useful: we now also disable/enable the network on sleep/resume. It does not seem to avoid all the assertion failures.

We see there is another error which seems to crash the app on Android and block part of the code on iOS. I've logged this separately as #2610 as I'm not sure if this is really related.

@Sroose
Copy link
Author

Sroose commented Feb 8, 2020

Extra note on the disableNetwork() suggestion: after some debugging, it seems the enableNetwork() does not always work.

Often, it does not do anything.

*afs.firestore.enableNetwork().then(
 () => console.log('Network re-enabled'),
 err => console.log('ERROR RE-ENABLING NETWORK ', err)
);

Nor the success or error messages are printed in these situations.

@schmidt-sebastian
Copy link
Contributor

@Sroose We are still figuring out how to address this properly, as this might involve a breaking API change since me may now have to return errors for operations that we previously decided simply could not fail.

@lupas
Copy link
Contributor

lupas commented Feb 25, 2020

Suffering from the same error, Firestore stops working & only solution is to restart the PWA. FYI: Also showed up on iOS 11.3, not only iOS 13.

My details:

Firebase SDK version: 7.8.1 & 7.9.0
Stack: Vue.js + Nuxt.js (SPA Mode) + Workbox
Error on: iOS 11.3, 13.3, 13.1.2, 13.31, Mobile Safari 13.0.1+

sentryTags

Error

@firebase/firestore: Firestore (7.8.1): FIRESTORE (7.8.1) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: transaction@[native code]
https://urloftheapp.com/_nuxt/67e3d4910d3ddfe67b0b.js:2:49096
https://urloftheapp.com/_nuxt/67e3d4910d3ddfe67b0b.js:2:47467
https://urloftheapp.com/_nuxt/67e3d4910d3ddfe67b0b.js:2:2016
https://urloftheapp.com/_nuxt/67e3d4910d3ddfe67b0b.js:2:1499
l@https://urloftheapp.com/_nuxt/67e3d4910d3ddfe67b0b.js:2:930
promiseReactionJob@[native code]

@lupas
Copy link
Contributor

lupas commented Mar 9, 2020

ONLY A WORKAROUND
This doesn't fix the issue and still throws the error, but for me this at least makes the app usable for the users:

  1. Intercept errors
  2. Check for that error with regExp
  3. Instead of throw it, do a window.location.reload()

That way, in case the error appears, the app gets reloaded on the current page and Firebase works again. The user - in my case - barely realizes that the app was reloaded, because the error appears usually (or always) when a PWA is opened again after a while.

Looks something like this in my Vue.js app:

const fatalErrorsRegExp = [
  'INTERNAL ASSERTION FAILED: AsyncQueue is already failed'
]
for (const fatalErrorRegExp of fatalErrorsRegExp) {
  const re = new RegExp(fatalErrorRegExp)
  const isMatch = re.test(error) || re.test(error.message)
  if (isMatch && window.location.hash !== '#retry') {
    // mark the page to don't trigger reload infinitely
    window.location.hash = '#retry'
    window.location.reload(true)
    return
  }
}

BTW: Also works well with general PWA chunk-errors (due to renamed chunks after a new release), in case you also get them in your app ;)

@DevDianDankie
Copy link

Also having an issue where firebase stops working after app is coming out of sleep. Thought I should post my logs here as well.

I am running our app on an ipad and the xcode target logs are as follows:

  • when turning the screen off:

2020-04-16 04:35:11.036507+0200 MyFarmWeb Capture[1436:912963] [Snapshotting] Snapshotting a view (0x106037a00, UIKeyboardImpl) that has not been rendered at least once requires afterScreenUpdates:YES.
2020-04-16 04:35:11.320738+0200 MyFarmWeb Capture[1436:912963] Can't end BackgroundTask: no background task exists with identifier 20 (0x14), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

  • a few seconds later (screen still off):

2020-04-16 04:35:37.401040+0200 MyFarmWeb Capture[1436:912963] [ProcessSuspension] Background task expired while holding WebKit ProcessAssertion (isMainThread? 1).

  • turning screen back on after a few minutes:

2020-04-16 04:41:30.211728+0200 MyFarmWeb Capture[1436:912963] [ProcessSuspension] 0x283c098c0 - WKProcessAssertionBackgroundTaskManager: Ignored request to start a new background task because the application is already in the background
2020-04-16 04:41:30.213360+0200 MyFarmWeb Capture[1436:912963] [ProcessSuspension] 0x283c098c0 - WKProcessAssertionBackgroundTaskManager: Ignored request to start a new background task because the application is already in the background
2020-04-16 04:41:30.288155+0200 MyFarmWeb Capture[1436:912963] CDVWKWebViewEngine shouldReloadWebView::
2020-04-16 04:41:30.288207+0200 MyFarmWeb Capture[1436:912963] CDVWKWebViewEngine shouldReloadWebView title: Ionic App
2020-04-16 04:41:30.288231+0200 MyFarmWeb Capture[1436:912963] CDVWKWebViewEngine shouldReloadWebView location: http://localhost:8080/
2020-04-16 04:41:30.288249+0200 MyFarmWeb Capture[1436:912963] CDVWKWebViewEngine shouldReloadWebView reload: 0
2020-04-16 04:41:30.292204+0200 MyFarmWeb Capture[1436:912963] ERROR: [2020-04-16T02:41:30.283Z] @firebase/firestore: Firestore (5.11.0): INTERNAL UNHANDLED ERROR: Attempt to open a cursor in database without an in-progress transaction
2020-04-16 04:41:30.292257+0200 MyFarmWeb Capture[1436:912963] ERROR: Unhandled Promise rejection: Attempt to open a cursor in database without an in-progress transaction ; Zone: ; Task: Promise.then ; Value: UnknownError: Attempt to open a cursor in database without an in-progress transaction
2020-04-16 04:41:37.544817+0200 MyFarmWeb Capture[1436:912963] ERROR: [2020-04-16T02:41:37.543Z] @firebase/firestore: Firestore (5.11.0): FIRESTORE (5.11.0) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: Attempt to open a cursor in database without an in-progress transaction

@joplaete
Copy link

joplaete commented May 12, 2020

Hey - any more news on this? Getting this often as well - firebase stops working when ios app resumes from background (in my case in ionic/capacitor setup). Is there a fix for this in the works somewhere or do we need to work around? Thanks!

@DevDianDankie
Copy link

@joplaete for now, just another workaround that is working for me is to use the ionic backgroundmode plugin. It keeps the app awake in background and when screen is off. For android it works well. But beware for ios -apple rejects it because the plugin references 'audio' for it's reason to keep the app from sleeping.

So you'd need to justify why the plugin in being used (the app basically needs audio feature).

@schmidt-sebastian
Copy link
Contributor

I am working on this as part of #2755.

@firebase firebase locked and limited conversation to collaborators Jan 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants