Async-storage: Android Crashes Caused by android.database.sqlite.SQLiteException

Created on 13 Sep 2019  路  13Comments  路  Source: react-native-async-storage/async-storage

Current behavior

I recently upgraded RN from 0.57 to 0.59 and moved to using this package for AsyncStorage and have seen about 2% of our users experience this crash so far.

Stack Trace

AsyncStorageModule.java line 208
com.reactnativecommunity.asyncstorage.AsyncStorageModule$2.doInBackgroundGuarded


Fatal Exception: java.lang.RuntimeException
An error occurred while executing doInBackground()
android.os.AsyncTask$3.done

Fatal Exception: java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done + 309(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion + 354(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException + 223(FutureTask.java:223)
at java.util.concurrent.FutureTask.run + 242(FutureTask.java:242)
at com.reactnativecommunity.asyncstorage.AsyncStorageModule$SerialExecutor$1.run + 61(AsyncStorageModule.java:61)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1113(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 588(ThreadPoolExecutor.java:588)
at java.lang.Thread.run + 818(Thread.java:818)


Caused by android.database.sqlite.SQLiteException
no such table: catalystLocalStorage (code 1): , while compiling: INSERT OR REPLACE INTO catalystLocalStorage VALUES (?, ?);
com.reactnativecommunity.asyncstorage.AsyncStorageModule$2.doInBackgroundGuarded

Caused by android.database.sqlite.SQLiteException: no such table: catalystLocalStorage (code 1): , while compiling: INSERT OR REPLACE INTO catalystLocalStorage VALUES (?, ?);
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(SQLiteConnection.java)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement + 896(SQLiteConnection.java:896)
at android.database.sqlite.SQLiteConnection.prepare + 507(SQLiteConnection.java:507)
at android.database.sqlite.SQLiteSession.prepare + 588(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram. + 58(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement. + 31(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.compileStatement + 1024(SQLiteDatabase.java:1024)
at com.reactnativecommunity.asyncstorage.AsyncStorageModule$2.doInBackgroundGuarded + 208(AsyncStorageModule.java:208)
at com.reactnativecommunity.asyncstorage.AsyncStorageModule$2.doInBackgroundGuarded + 199(AsyncStorageModule.java:199)
at com.facebook.react.bridge.GuardedAsyncTask.doInBackground + 32(GuardedAsyncTask.java:32)
at com.facebook.react.bridge.GuardedAsyncTask.doInBackground + 20(GuardedAsyncTask.java:20)
at android.os.AsyncTask$2.call + 295(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run + 237(FutureTask.java:237)
at com.reactnativecommunity.asyncstorage.AsyncStorageModule$SerialExecutor$1.run + 61(AsyncStorageModule.java:61)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1113(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 588(ThreadPoolExecutor.java:588)
at java.lang.Thread.run + 818(Thread.java:818)

Expected behavior

To not crash.

Repro steps

Unable to reproduce, only seen occurring in Production across a variety of devices and Android versions.

Environment

  • Async Storage version: 1.5.1
  • React-Native version: 0.59.10
  • Platform tested: Android
  • Logs/Error that are relevant: See above

All 13 comments

@danielvportlandia Can you share what kind of android version/phones have this issue?

@Krizzu Here is the spread according to Firebase, happening on all versions though only 1% occurring on Android 9.0.

image

I am also running into this issue with the below call stack. It is happening on multiple devices in production app. I am not able reproduce it in dev environment though. Please note the error message table catalystLocalStorage already exists (code 1). I feel this can help debug the problem.

java.lang.RuntimeException: 
An error occured while executing doInBackground()
  at android.os.AsyncTask$3.done (AsyncTask.java:309)
  at java.util.concurrent.FutureTask.finishCompletion (FutureTask.java:354)
  at java.util.concurrent.FutureTask.setException (FutureTask.java:223)
  at java.util.concurrent.FutureTask.run (FutureTask.java:242)
  at com.reactnativecommunity.asyncstorage.AsyncStorageModule$SerialExecutor$1.run (AsyncStorageModule.java:62)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1113)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:588)
  at java.lang.Thread.run (Thread.java:818)
Caused by: android.database.sqlite.SQLiteException: 
table catalystLocalStorage already exists (code 1)
  at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration (SQLiteConnection.java:400)
  at android.database.sqlite.SQLiteConnection.open (SQLiteConnection.java:221)
  at android.database.sqlite.SQLiteConnection.open (SQLiteConnection.java:196)
  at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked (SQLiteConnectionPool.java:463)
  at android.database.sqlite.SQLiteConnectionPool.open (SQLiteConnectionPool.java:185)
  at android.database.sqlite.SQLiteConnectionPool.open (SQLiteConnectionPool.java:177)
  at android.database.sqlite.SQLiteDatabase.openInner (SQLiteDatabase.java:836)
  at android.database.sqlite.SQLiteDatabase.open (SQLiteDatabase.java:821)
  at android.database.sqlite.SQLiteDatabase.openDatabase (SQLiteDatabase.java:714)
  at android.app.ContextImpl.openOrCreateDatabase (ContextImpl.java:576)
  at android.content.ContextWrapper.openOrCreateDatabase (ContextWrapper.java:269)
  at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked (SQLiteOpenHelper.java:223)
  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:163)
  at com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.ensureDatabase (ReactDatabaseSupplier.java:88)
  at com.reactnativecommunity.asyncstorage.AsyncStorageModule.ensureDatabase (AsyncStorageModule.java:435)
  at com.reactnativecommunity.asyncstorage.AsyncStorageModule.access$000 (AsyncStorageModule.java:35)
  at com.reactnativecommunity.asyncstorage.AsyncStorageModule$1.doInBackgroundGuarded (AsyncStorageModule.java:135)
  at com.reactnativecommunity.asyncstorage.AsyncStorageModule$1.doInBackgroundGuarded (AsyncStorageModule.java:132)
  at com.facebook.react.bridge.GuardedAsyncTask.doInBackground (GuardedAsyncTask.java:32)
  at com.facebook.react.bridge.GuardedAsyncTask.doInBackground (GuardedAsyncTask.java:20)
  at android.os.AsyncTask$2.call (AsyncTask.java:295)
  at java.util.concurrent.FutureTask.run (FutureTask.java:237)
Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: 
  at android.database.sqlite.SQLiteConnection.nativeExecute (Native Method)
  at android.database.sqlite.SQLiteConnection.execute (SQLiteConnection.java:562)
  at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration (SQLiteConnection.java:387)

We have the same crashes in firebase. I guess it crashes an app when use Async Storage in background.
In my case it was a bug to run Permissions on background which invoke Async Storage. But still it shouldn't crash the app.

    if (nextAppState === 'background') {
        Permissions.check('camera').then(()= > { //Permissions use Async Storage
                ...
        });
    }

Environment

  • Async Storage version: 1.6.1
  • React-Native version: 0.59.10
  • react-native-permissions: 1.2.1

It's still reproduced in my app. So background fix didn't help us.

The exception like this is happening on my app too.

Crash log as follows :

# AsyncTask #2(8484)
android.database.sqlite.SQLiteReadOnlyDatabaseException
attempt to write a readonly database (code 1032)

1聽java.lang.RuntimeException:An error occurred while executing doInBackground()
2聽android.os.AsyncTask$3.done(AsyncTask.java:325)
3聽......
4聽Caused by:
5聽android.database.sqlite.SQLiteReadOnlyDatabaseException:attempt to write a readonly database (code 1032)
6聽android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
7聽android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:631)
8聽android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:456)
9聽android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:245)
10聽android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:220)
11聽android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
12聽android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
13聽android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
14聽android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:843)
15聽android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:828)
16聽android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:721)
17聽android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:769)
18聽android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:300)
19聽android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
20聽android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
21聽com.reactnativecommunity.asyncstorage.ReactDatabaseSupplier.ensureDatabase(ReactDatabaseSupplier.java:88)
22聽com.reactnativecommunity.asyncstorage.AsyncStorageModule.ensureDatabase(AsyncStorageModule.java:429)
23聽com.reactnativecommunity.asyncstorage.AsyncStorageModule.access$000(AsyncStorageModule.java:34)
24聽com.reactnativecommunity.asyncstorage.AsyncStorageModule$6.doInBackgroundGuarded(AsyncStorageModule.java:399)
25聽com.reactnativecommunity.asyncstorage.AsyncStorageModule$6.doInBackgroundGuarded(AsyncStorageModule.java:396)
26聽com.facebook.react.bridge.GuardedAsyncTask.doInBackground(GuardedAsyncTask.java:32)
27聽com.facebook.react.bridge.GuardedAsyncTask.doInBackground(GuardedAsyncTask.java:20)
28聽android.os.AsyncTask$2.call(AsyncTask.java:305)
29聽java.util.concurrent.FutureTask.run(FutureTask.java:237)
30聽com.reactnativecommunity.asyncstorage.AsyncStorageModule$SerialExecutor$1.run(AsyncStorageModule.java:61)
31聽java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
32聽java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
33聽java.lang.Thread.run(Thread.java:761)

Else Info :

System: Android 7.1.1,level 25
CPU: arm64-v8a
Front and Background State: Background

The source code at ReactDatabaseSupplier.java:88 :

  /**
   * Verify the database exists and is open.
   */
  /* package */ synchronized boolean ensureDatabase() {
    if (mDb != null && mDb.isOpen()) {
      return true;
    }
    // Sometimes retrieving the database fails. We do 2 retries: first without database deletion
    // and then with deletion.
    SQLiteException lastSQLiteException = null;
    for (int tries = 0; tries < 2; tries++) {
      try {
        if (tries > 0) {
          deleteDatabase();
        }
        mDb = getWritableDatabase();                     // line 88
        break;
      } catch (SQLiteException e) {
        lastSQLiteException = e;
      }
      // Wait before retrying.
      try {
        Thread.sleep(SLEEP_TIME_MS);
      } catch (InterruptedException ie) {
        Thread.currentThread().interrupt();
      }
    }
    if (mDb == null) {
      throw lastSQLiteException;
    }
    // This is a sane limit to protect the user from the app storing too much data in the database.
    // This also protects the database from filling up the disk cache and becoming malformed
    // (endTransaction() calls will throw an exception, not rollback, and leave the db malformed).
    mDb.setMaximumSize(mMaximumDatabaseSize);
    return true;
  }
  • It seems we already have do something to avoid the SQLiteException, but actually it still happening when the app is in background.
  • As an Android native developer, it is hard to find a way to fix.

@zhuanghongji Do you have any reproduction steps or a project I could jump in and debug?

We have finally found a solution. The crash hasn't been reproduced in our last release.
One of libs uses AsyncStorage from react-native and the rest part of app use AsyncStorage from @react-native-community/async-storage.
The package was react-navigation 2.18.3. We created patch using npm patch-package-package

@Krizzu Actually, i had tried my best to find any reproduction steps but i can't find it now. The crash log is just copy from the Bugly (an exception reporting tool from Tencent).

@StanislavMayorov Here is my dependencies before:

"dependencies": {
    "@ant-design/react-native": "3.1.9",
    "@react-native-community/async-storage": "1.5.0",
    "@react-native-community/cameraroll": "^1.2.1",
    "@types/react-native-snap-carousel": "^3.7.4",
    "react": "16.8.3",
    "react-native": "0.59.9",
    "react-native-autotrack-growingio": "0.0.6",
    "react-native-gesture-handler": "1.3.0",
    "react-native-htmlview": "^0.15.0",
    "react-native-keyboard-aware-scroll-view": "^0.9.1",
    "react-native-linear-gradient": "2.5.4",
    "react-native-qrcode-svg": "5.3.2",
    "react-native-snap-carousel": "^3.8.4",
    "react-native-svg": "9.13.3",
    "react-native-swiper": "1.5.14",
    "react-native-view-shot": "^3.0.2",
    "react-navigation": "3.11.0",
  },

When i "Find in folder" in node_modules, i see there is import { AsyncStorage, ... } from 'react-native' in @bang88/react-native-utilmate-listview/src/refreshableScrollView.android.js

In the next version app, i will try to upgrade the @react-native-community/async-storage to the latest release to see if any more Crash.

When i "Find in folder" in node_modules, i see there is import { AsyncStorage, ... } from 'react-native' in @bang88/react-native-utilmate-listview/src/refreshableScrollView.android.js

@zhuanghongji yes, we had the similar case. Did you fork or update @bang88/react-native-utilmate-listview package to use @react-native-community/async-storage?

https://github.com/react-native-community/async-storage/issues/118#issuecomment-500138053 explains why the AsyncStorage version/package matters. I don't know if it could cause the 1032 or 1 error codes mentioned in this issue.

Closing due to inactivity.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alex-mironov picture alex-mironov  路  71Comments

josmithua picture josmithua  路  20Comments

dominiczaq picture dominiczaq  路  22Comments

Waqas-Jani picture Waqas-Jani  路  28Comments

muhammadn picture muhammadn  路  58Comments