firebase-js-sdk icon indicating copy to clipboard operation
firebase-js-sdk copied to clipboard

Refusing to open IndexedDB database due to potential corruption

Open luke-rogers opened this issue 6 months ago • 19 comments

Operating System

iOS 18.*

Environment (if applicable)

Mobile Safari Version 16.1

Firebase SDK Version

11.6.1

Firebase SDK Product(s)

Firestore

Project Tooling

Angular

Detailed Problem Description

After the changes introduced in PR #8871, we’ve observed a significant number of IndexedDB initialization failures caused by this new conditional block:

if (
  this.lastClosedDbVersion !== null &&
  this.lastClosedDbVersion !== event.oldVersion
) {
  throw new Error(
    `refusing to open IndexedDB database due to potential ` +
      `corruption of the IndexedDB database data; this corruption ` +
      `could be caused by clicking the "clear site data" button in ` +
      `a web browser; try reloading the web page to re-initialize ` +
      `the IndexedDB database: ` +
      `lastClosedDbVersion=${this.lastClosedDbVersion}, ` +
      `event.oldVersion=${event.oldVersion}, ` +
      `event.newVersion=${event.newVersion}, ` +
      `db.version=${db.version}`
  );
}

This logic is now throwing for many first-time users of our app, particularly on iOS devices, where we see:

  • event.oldVersion = 0
  • lastClosedDbVersion = 17
  • event.newVersion = 17
  • db.version = 17

Impact

We’ve seen this error reported from 69 unique users, many of whom appear to be encountering it on first app open, likely with a fresh install. This completely blocks their ability to use the app, even though the database is likely in a clean state.

Steps and code to reproduce issue

We've been unable to reproduce it ourselves

luke-rogers avatar May 22 '25 12:05 luke-rogers

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

google-oss-bot avatar May 22 '25 12:05 google-oss-bot

@luke-rogers, are there other frameworks in the mix here, like Ionic or Capacitor?

MarkDuckworth avatar May 22 '25 14:05 MarkDuckworth

Yes, there are other frameworks like Ionic and Capacitor.

Most of of these events are coming for users in the browser though. 88% of the events are from 'web'.

Image

Here is how we initialise Firebase. We only user indexedDBLocalPersistence when Capacitor.isNativePlatform() is true.

function initializeFirestoreDb() {
    return initializeFirestore(getApp(), {
        ignoreUndefinedProperties: true,
        localCache: persistentLocalCache({
            cacheSizeBytes: CACHE_SIZE_UNLIMITED,
            tabManager: persistentMultipleTabManager(),
        }),
    });
}

function initializeAuthProvider() {
    return Capacitor.isNativePlatform()
        ? initializeAuth(getApp(), { persistence: indexedDBLocalPersistence })
        : getAuth();
}

luke-rogers avatar May 22 '25 15:05 luke-rogers

That seems plausible that #8871 is the culprit here. That PR was first included in version 11.6.1 (released April 24, 2025). Are you able to downgrade to version 11.6.0 (or earlier) in the meantime, while investigation is underway?

dconeybe avatar May 22 '25 16:05 dconeybe

Yes, we have just downgraded to version 11.6.0. Thanks.

luke-rogers avatar May 22 '25 16:05 luke-rogers

I've been unable to reproduce the "refusing to open IndexedDB database due to potential corruption" error reported in the OP. The IndexedDB usage with multi-tab persistence is working as expected for me. I tried in macOS Safari and iOS simulator Safari using a very-barebones web application.

@luke-rogers Are you at all able to capture the console logs leading up to the error?

Also, would you be able to create a "hello world" application that mimics the design of your production application and share it (e.g. via a github repo)? If you could also include a sample of the Firestore operations that your app performs that would be helpful too. In the meantime I'll keep investigating. Thank you.

dconeybe avatar May 22 '25 17:05 dconeybe

I’ve been trying to reproduce this in macOS Safari and the iOS simulator without success so far, but I’ll keep digging. I also don’t yet have any console logs I can share but I’ll aim to capture those where possible. I assume ideally you're wanting the Firebase debug logs here? I’ll also work on putting together a sample repo to help isolate the conditions, that might take a bit of time but I’ll share once available.

Overall I'm confident many of the cases we’re seeing, users are not clearing site data. This is especially true for our mobile app users, especially where this failure is being triggered the first time they ever open the app in most instances. We’re also seeing the error across platforms - both desktop and mobile, and across Safari and Chrome, though it remains most prevalent on iOS.

The real problem is that this error leaves the Firestore client completely unusable until the page is reloaded, but for mobile app users (especially when running in a WebView or PWA), a page refresh isn’t always possible or intuitive. This results in a broken experience that users can’t easily recover from. Is there a first party way in Firebase we can know when we should refresh the users page in this scenario?

In all the cases we’ve observed, event.oldVersion === 0, and lastClosedDbVersion is a non-zero value, such as 17.

Browser Count Percentage
HeadlessChrome 127.0.6533 19 21.11
Mobile Safari 18.4 16 17.78
Mobile Safari 18.3.1 11 12.22
Edge 136.0.0 6 6.67
Chrome Mobile WebView 136.0.7103 5 5.56
Chrome 117.0.5938 5 5.56
Chrome 136.0.0 4 4.44
Unknown 3 3.33
Apple Mail 605.1.15 3 3.33
Safari 18.3.1 2 2.22
Safari 18.4 2 2.22
Edge Mobile 135.0.3179 2 2.22
Mobile Safari 18.3 2 2.22
Safari 18.1.1 1 1.11
Edge 135.0.0 1 1.11
Safari 18.0.1 1 1.11
Mobile Safari 16.1 1 1.11
Chrome Mobile 135.0.0 1 1.11
Safari 17.6 1 1.11
Mobile Safari 16.2 1 1.11
Mobile Safari 18.1.1 1 1.11
Chrome 134.0.0 1 1.11
Safari 18.1 1 1.11
OS Count Percentage
iOS 18.4.1 20 22.22
Unknown 19 21.11
Windows >=10 16 17.78
Mac OS X >=10.15.7 12 13.33
iOS 18.3.2 11 12.22
Android 13 3 3.33
iOS 18.3.1 2 2.22
Android 12 2 2.22
iOS 18.1.1 1 1.11
iOS 16.2 1 1.11
Android 10 1 1.11
iOS 18.5 1 1.11
iOS 16.1.1 1 1.11
App Type Count Percentage
Web App 79 87.78
Mobile App (Capacitor) 11 12.22

luke-rogers avatar May 23 '25 08:05 luke-rogers

@luke-rogers Thank you for this extra information. That is, indeed, curious that the bug is not limited to Safari, but also happens in Chrome.

My eye was drawn to "HeadlessChrome" in your chart, as it sounds like it could be related to your integration tests using a framework like Puppeteer (https://pptr.dev/) which is commonly used to launch a headless chrome browser. If that is the case, are you able to reproduce this bug in your CI? If so, perhaps you could examine and/or capture the console log output.

And by "console logs", yes, I mean Firebase debug logs. That's why I'm specifically interested if you can repro this bug in your CI because then you could enable Firestore debug logging and those logs would be incredibly insightful.

I'll keep digging. I'm mostly perplexed why db.version = 17 but event.oldVersion = 0. It seems like the upgradeneeded event on an IDBOpenDBRequest is being triggered unnecessarily since the DB is already at version 17 but the event is suggesting that it should be version 0.

dconeybe avatar May 23 '25 14:05 dconeybe

@dconeybe we don't actually run any integration tests against our production environment. All the HeadlessChrome errors seemed to come from a single IP address range 205.169.39.x, which I'm guessing must be some sort of bot/scraper?

I do wonder if there are some settings you could launch headless Chrome with that would consistently trigger this issue. Happy to take a look into that if we think that'd be a valid test scenario? I am also still primarily trying to reproduce this using Safari given it seems to be most prevalent there.

From the code, for this error it even occur close has been called at some point for lastClosedDbVersion to be 17. Are there any scenarios in the Firebase codebase triggered that?

luke-rogers avatar May 23 '25 16:05 luke-rogers

Oh interesting. Yeah, that would make sense that "HeadlessChrome" would be a bot/scraper, or perhaps someone who has automated their workflow :) My gut instinct is that "HeadlessChrome" is not necessarily more susceptible to the error but, rather, that the absolute number of requests from this browser is larger, leading to more occurrences.

I have a question, though, based on your last comment. You said this:

From the code, for this error it even occur close has been called at some point for lastClosedDbVersion to be 17. Are there any scenarios in the Firebase codebase triggered that?

I'm not sure I understand what you mean. Could you explain?

dconeybe avatar May 23 '25 19:05 dconeybe

Sorry, I should have been more clear.

To help me better understand and attempt to create a reliable reproduction for this issue, I wanted to ask specifically about lastClosedDbVersion. As far as I can tell, it’s only set within the close event callback. Outside of clearing the site data manually, do you happen to know when else this event might actually be triggered?

In particular, I’m curious whether scenarios like memory pressure or the app being backgrounded (especially on mobile Safari or WKWebView) could cause the browser to forcibly close the IndexedDB connection. I know iOS is quite aggressive with resource management and suspending background tabs or apps, and I’ve seen reports that these conditions might trigger a close event even without explicit user action. If that’s the case, it would explain why we’re seeing this mismatch between lastClosedDbVersion and oldVersion despite no apparent site data reset.

Also, I noticed the issue was closed as completed, was that intentional?

luke-rogers avatar May 23 '25 19:05 luke-rogers

I've re-opened the issue. I didn't mean to close it.

Looking at the documentation for the close event more closely (https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/close_event) it says this:

The close event is fired on IDBDatabase when the database connection is unexpectedly closed. This could happen, for example, if the underlying storage is removed or if the user clears the database in the browser's history preferences.

Note that it is not fired if the database connection is closed normally using IDBDatabase.close().

My code seems to assume that the close event is fired both or normal and on abnormal closing, which is incorrect.

From reading around the web, it seems plausible that something could be going wrong if the web site is opened in two different tabs. Could you try reproducing with the site opened in two different tabs, and refreshing one, etc?

dconeybe avatar May 23 '25 20:05 dconeybe

For posterity, here is the app I was playing around with to try to understand IndexedDB behavior and reproduce the observed behavior: https://github.com/dconeybe/IdbVersionIssue9056/

dconeybe avatar May 24 '25 03:05 dconeybe

Thanks for reopening the issue, and yes, I agree the close event behaviour is a bit opaque. Based on the MDN docs and reading around it definitely seems like there are multiple edge cases across environments that can trigger it.

I tried the two-tabs-and-refresh scenario you mentioned, but it didn’t seem to trigger the error in my setup. Both tabs remained connected without hitting the oldVersion = 0 + lastClosedDbVersion = 17 condition.

I’ll take a look at your example repo, thanks for sharing that! I’ll try to reproduce the IndexedDB behaviour in that context and see if I can spot anything that might help narrow this down further.

luke-rogers avatar May 27 '25 08:05 luke-rogers

@luke-rogers I'm still stumped about this issue. Is there any way you can publish a version of your application that uses the problematic firebase sdk version 11.6.1 and give me a user account that I can play around with, trying to reproduce the error?

dconeybe avatar May 30 '25 15:05 dconeybe

@dconeybe I've invited you to this repo which has details of a deployment using Firebase SDK version 11.6.1. The credentials are in the README.

Please let me know if you need anything else.

luke-rogers avatar Jun 02 '25 08:06 luke-rogers

@luke-rogers I've been able to log into your app. The console logs are nearly empty though. Are you able to enable Firestore debug logging by calling import {setLogLevel} from "firebase/firestore"; setLogLevel('debug')?

dconeybe avatar Jun 02 '25 18:06 dconeybe

@dconeybe I've enabled the debug logs.

luke-rogers avatar Jun 02 '25 18:06 luke-rogers

@luke-rogers Do you, by any chance, call clearIndexedDbPersistence() in your application?

dconeybe avatar Jun 06 '25 18:06 dconeybe

@luke-rogers Do you, by any chance, call clearIndexedDbPersistence() in your application?

We are seeing this issue as well in our app and we do call this method. We also suffered from: https://github.com/firebase/firebase-js-sdk/issues/8593

We would really appreciate to see a fix here :)

boldtrn avatar Jun 18 '25 08:06 boldtrn

@boldtrn Thank you for this extra information. I just returned from vacation and will continue investigating this. Do you, by any chance, have a reproducible scenario that causes the "refusing to open IndexedDB database due to potential corruption" error? I have not been able to reproduce this error, except by explicitly clicking "clear site data" in a web browser, in which case the error is expected to guard against database corruption.

dconeybe avatar Jun 20 '25 14:06 dconeybe

No sorry, we only see the errors in production. We don't have a reproducible sample.

boldtrn avatar Jun 20 '25 14:06 boldtrn

Update: I am working on adding a hidden setting to FirestoreSettings that would enable users to opt-out of the updated logic to preemptively terminate the Firestore instance if "Clear Site Data" is detected. This will allow apps to opt into the logic that was in place before https://github.com/firebase/firebase-js-sdk/pull/8871. This new setting will not be available in today's release of the firebase-js-sdk, but should be available in the release 3 weeks from now (circa Jul 17, 2025). I will update this thread once it's available.

If interested in the low-level details, see https://github.com/firebase/firebase-js-sdk/pull/9087 and https://github.com/firebase/firebase-js-sdk/pull/9118. There will be one more PR in that series to finally add the new setting to FirestoreSettings.

Thank you all for your patience on this issue. If you happen to reproduce the bug, or are able to capture debug logs from a customer who reproduces the issue, please provide those logs. With the inability to reproduce it is a giant mystery to me what is going on :(

dconeybe avatar Jun 26 '25 15:06 dconeybe

Note to self: It looks like we got "lucky" and reproduced the issue noted in the OP in our CI tests: https://github.com/firebase/firebase-js-sdk/actions/runs/16131442609/job/45519708116?pr=9154. This gives me a potential reproducible scenario to investigate.

Here are the logs, in case they get GC'd by github in the meantime:

logs_41327024904.zip

dconeybe avatar Jul 08 '25 15:07 dconeybe

I've fixed this issue by reverting the problematic PR in https://github.com/firebase/firebase-js-sdk/pull/9162. The fix will be included in the next release, expected to be about a week from now (mid-July 2025).

Please follow the re-opened bug https://github.com/firebase/firebase-js-sdk/issues/8593 if the issue that was fixed by the problematic PR is of interest to you.

dconeybe avatar Jul 11 '25 18:07 dconeybe