firebase-android-sdk: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence.

Environment

  • Firebase Component:
'firebase_analytics'                      : '21.2.2'
'firebase_crashlytics_gradle'             : '2.9.0'
'firebase_crashlytics'                    : '18.3.7'
'firebase_messageing'                     : '23.1.2'
'firebase_auth'                           : '22.0.0'
'firebase_storage'                        : '20.2.0'
'firestore_ktx'                           : '24.6.0'
'firebase_config_ktx'                     : '21.4.0'
'firebase_perf_ktx'                       : '20.3.2'
'functions_ktx'                           : '20.3.0'
'firebase_perf_gradle'                    : '1.4.2'
'firebase_core'                           : '21.1.1'

Problem

We are constantly receiving spikes of crashes related to the Firestore. Seems like something related to the sqlite db lock. Messages say that could be multiprocess issue when Application class gets initialized by multiple processes but we do not have it configured explicitly. I don’t know any other ways that it could happen. On our devices we are not able to reproduce the issue.

Caused by java.lang.RuntimeException: java.lang.RuntimeException: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them. at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1(AsyncQueue.java:30) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:15) at java.lang.Thread.run(Thread.java:764)

Caused by android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode at android.database.sqlite.SQLiteConnection.nativePrepareStatement(SQLiteConnection.java) at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:903) at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:648) at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:334) at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:306) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:216) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:194) at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:493) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:200) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:192) at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:869) at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:854) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:729) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:719) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:295) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:238) at com.google.firebase.firestore.local.SQLitePersistence.u1(SQLitePersistence.java:17) at com.google.firebase.firestore.core.ComponentProvider.initialize(ComponentProvider.java:68) at com.google.firebase.firestore.core.FirestoreClient.initialize(FirestoreClient.java:68) at com.google.firebase.firestore.core.FirestoreClient.lambda$new$0(FirestoreClient.java:48) at com.google.firebase.firestore.util.AsyncQueue.lambda$enqueue$2(AsyncQueue.java:2) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1(AsyncQueue.java:16) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:15) at java.lang.Thread.run(Thread.java:764)

Stacktrace
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="***">
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:name=".App"
    android:allowBackup="false"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:localeConfig="@xml/locales_config"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <activity
        android:name="***"
        android:exported="true"
        android:launchMode="singleTask"
        android:theme="@style/AppTheme.Launcher">

    </activity>
    <activity
        android:name="***"
        android:exported="true"
        android:launchMode="singleTask"
        android:theme="@style/AppTheme.Launcher">

    </activity>
    <activity
        android:name="***"
        android:exported="true"
        android:launchMode="singleTask"
        android:theme="@style/AppTheme.Launcher">

    </activity>

    <activity
        android:name=".ui.screen.splash.SplashActivity"
        android:exported="true"
        android:screenOrientation="userPortrait"
        android:theme="@style/AppTheme.Launcher">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".ui.screen.main.MainActivity"
        android:screenOrientation="userPortrait"
        android:windowSoftInputMode="adjustPan" />

</application>
</manifest> Android manifest</summary

Screenshot 2023-05-16 at 00 58 38

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 1
  • Comments: 19 (6 by maintainers)

Most upvoted comments

I didn’t tried, it is not good to test this with users on production… I disabled the offline functionality.

@hakobast It is only a guess or an assumption: The database file is locked. (database is locked (code 5): , while compiling: PRAGMA journal_mode)

Maybe there is a connection to this issue.

I found a workaround. You have to disable the persistence on devices with 32 bit processor.

FirebaseFirestore.instance.settings = FirebaseFirestore.instance.settings.copyWith(
  persistenceEnabled: false,
);

I’m using this code now, so I’m not checking if the device architecture so far. Crash is no longer happening then.

    final androidInfoInfo = await DeviceInfoPlugin().androidInfo;
    const ANDROID_12_LEVEL = 32;
    final isAndroid12OrLess = androidInfoInfo.version.sdkInt <= ANDROID_12_LEVEL;
    if (isAndroid12OrLess) {
      FirebaseFirestore.instance.settings = FirebaseFirestore.instance.settings.copyWith(
        persistenceEnabled: false,
      );
    }