Apps-android-commons: App keeps crashing on opening

Created on 30 Mar 2020  路  29Comments  路  Source: commons-app/apps-android-commons

Summary:

App keeps crashing on opening.

Steps to reproduce:

I cloned the repo from GitHub and tried to compile it. Can't open the app now.

System logs:

2020-03-30 22:05:52.054 13692-13692/fr.free.nrw.commons.beta E/LoadedApk: Unable to instantiate appComponentFactory
    java.lang.ClassNotFoundException: Didn't find class "fr.free.nrw.commons.beta.commons" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/fr.free.nrw.commons.beta-YxpmNSMHaflmNsRTrCV_tw==/base.apk"],nativeLibraryDirectories=[/data/app/fr.free.nrw.commons.beta-YxpmNSMHaflmNsRTrCV_tw==/lib/arm64, /data/app/fr.free.nrw.commons.beta-YxpmNSMHaflmNsRTrCV_tw==/base.apk!/lib/arm64-v8a, /system/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.LoadedApk.createAppFactory(LoadedApk.java:228)
        at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:733)
        at android.app.LoadedApk.getClassLoader(LoadedApk.java:812)
        at android.app.LoadedApk.getResources(LoadedApk.java:1034)
        at android.app.ContextImpl.createAppContext(ContextImpl.java:2357)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5821)
        at android.app.ActivityThread.access$1200(ActivityThread.java:200)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1673)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6810)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

2020-03-30 23:19:13.076 28318-28375/fr.free.nrw.commons D/OkHttp: --> GET https://commons.wikimedia.org/w/api.php?format=json&formatversion=2&errorformat=plaintext&action=query&list=logevents&letype=upload&leprop=title|timestamp|ids&lelimit=500&leuser=Anmol1311
2020-03-30 23:19:13.077 28318-28318/fr.free.nrw.commons E/ContributionsFragment: onFragmentResumed fr.free.nrw.commons.contributions.ContributionsListFragment
2020-03-30 23:19:13.084 28318-28373/fr.free.nrw.commons E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
    Process: fr.free.nrw.commons, PID: 28318
    java.lang.RuntimeException: Exception while computing database live data.
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
        at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:154)
        at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:142)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:409)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:298)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:92)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:53)
        at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
        at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:324)
        at androidx.room.util.DBUtil.query(DBUtil.java:83)
        at fr.free.nrw.commons.contributions.ContributionDao_Impl$10.call(ContributionDao_Impl.java:666)
        at fr.free.nrw.commons.contributions.ContributionDao_Impl$10.call(ContributionDao_Impl.java:663)
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)聽
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)聽
        at java.lang.Thread.run(Thread.java:764)聽
2020-03-30 23:19:13.085 28318-28375/fr.free.nrw.commons D/CookieManager: Domain:commons.wikimedia.org
2020-03-30 23:19:13.090 28318-28373/fr.free.nrw.commons E/ACRA: ACRA caught a RuntimeException for fr.free.nrw.commons
    java.lang.RuntimeException: Exception while computing database live data.
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
        at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:154)
        at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:142)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:409)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:298)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:92)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:53)
        at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
        at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:324)
        at androidx.room.util.DBUtil.query(DBUtil.java:83)
        at fr.free.nrw.commons.contributions.ContributionDao_Impl$10.call(ContributionDao_Impl.java:666)
        at fr.free.nrw.commons.contributions.ContributionDao_Impl$10.call(ContributionDao_Impl.java:663)
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)聽
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)聽
        at java.lang.Thread.run(Thread.java:764)聽

Device and Android version:

Redmi Note 5 Pro
MIUI version 11
Android 9

Commons app version:

master betaDebug

bug high priority

Most helpful comment

@6point022 I know this isn't a solution to the actual problem you've reported. But just try clearing the app's data and using the app. You would not experience the crash.

All 29 comments

Does this happen in the prod build variant?

Yes, it happens on prodDebug too.

I have added some more system logs that I missed earlier.

@6point022 I know this isn't a solution to the actual problem you've reported. But just try clearing the app's data and using the app. You would not experience the crash.

The reason for the actual problem is very clear in the error message. Quoting the relevant portion:

Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.

But just try clearing the app's data and using the app. You would not experience the crash.

@sivaraam Thanks a lot, it worked! :D

Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.

Let me add some information about why we're facing this issue based on the little knowledge about Room that I have.

As the error message clearly states the schema has changed without the version number being changed.

  • _What constitutes the schema here?_
    For now, it's the fields of the Contribution class that are persisted.

  • _When was it changed/Who changed it?_
    I suspect the crash observed here might be due to a change to the Contribution class done in PR #3569.

  • _Why didn't we catch this during testing?_
    It's complicated. In simple terms: a fresh app install wouldn't have caught the issue. As the validation would fail only when there's an existing version of the app installed and we install a new one that would introduce a schema conflict.

  • _How do we avoid this in future?_
    We would have to ensure that the schema version number of is updated whenever the fields of the classes being persisted using room are changed.

Kindly correct me if I'm wrong somewhere as what I've mentioned is purely based on what I remember and it's been rusty for a while. :slightly_smiling_face:

cc @misaochan

I am also facing the same issue on fresh install. @ashishkumar468 Can this be related to your recent change?

@maskaravivek. Not sure (None of my recent PR's have updated the schema), I will have a look, even if because of some reason, the schema was updated, it should not throw an exception on fresh installs, are you sure you faced the same on fresh installs?

I just noticed that even on uninstalling the app and reinstalling the data wasn't cleared. Once I clear all app data, it works for me.

That's weird, uninstalling should clear data.

@ashishkumar468 yes you are right this happened to me when I switched branch from master to 2.13-release but upon reinstalling it got fixed

Yes, one of the PR' must-have updated the schema. Should not be an issue though, because since room has been added, no releases have been made. So for end-user, this won't make a difference, although we should add migrations whenever a schema update is done.

Ah, okay. I can remove this from the release list then, but we would need to make sure that this doesn't happen again in the future (because then it will impact end users).

I just noticed that even on uninstalling the app and reinstalling the data wasn't cleared. Once I clear all app data, it works for me.

The same thing happened for me. Uninstalling and reinstalling didn't work, only clearing app data manually via Settings worked.

are ye running gradlew uA (or uninstallAll if you write out full gradle commands)? I would hazard the issue is uninstalling beta and not prod or vice versa. I have never run into this issue.

There should be no AppData to clear if it is fully uninstalled

Oh, right! Yes, I had beta installed, whoops.

Is there something here to do or can we close this?

I would like to discuss if there is a way to ensure that this doesn't happen again in the future - we were lucky that Room was implemented post the last release, but if we weren't then this would be impacting end users. Is there a process that we can implement that must be followed for schema updates, perhaps?

There are 2 camps for this, or at least 2 that I have followed

  1. Every change to the database write a migration
  2. Every release write a migration at the end

At release time testing that we can update from a previous version should be done regardless because you need to test your migration code.

I favour 2 though it does require some ownership of that code from someone at release time.

1 can be a bit hard to catch I find especially since so many people could add/remove/rename a field on a model and not see that that has an effect on the database.

Regardless we should all be following the advice of Barty Crouch pretending to be Mad Eye Moody, constant vigilance!

Option 2 sounds good if we are confident we won't miss that before release (else we get a lot of angry users!).

I'm just wondering about one other thing though. AFAIK, we frequently publish alpha versions to play store. If we push the migration to just before release those intermediate alpha updates would result in a crash (if the schema is changed, of course), wouldn't it? Would that be fine as it's just the alpha version?

I'm just wondering about one other thing though. AFAIK, we frequently publish alpha versions to play store. If we push the migration to just before release those intermediate alpha updates would result in a crash (if the schema is changed, of course), wouldn't it?

yes, right. the app will crash for them.

I guess we should go with option 1 as on every commit to master an alpha release is made.

Also, from a maintenance standpoint, it might be easier to have migrations for every change.

It is that or communicate to alpha users that they will need a fresh install on some versions, alphas are never renowned for their stability.

The thing I don't like about option 1 is how much extra code it adds but it is the "safer" option and causes less friction for our alpha users

I would be in favour of option 1 as well. While I'm sure our alpha testers will understand, we would still want to reduce the number of crashes that they encounter, if only because we will have to sift through all of the crash reports to find the "real" reports in the sea of "schema update" reports.

As you guys have said, it is safer as well and there is clear code ownership.

There is 1 more alternative if we don't particularly care about migrating our data between app versions

.fallbackToDestructiveMigration()

It isn't great but as long as we keep increasing the schema number there are no crashes. There is no data retention between versions though.

We could run a hybrid of option 2 and this, I am pretty sure a Migration can be to any arbitrary greater integer eg our first app version launches with v1 and the next app version launches with v100, we only have 1 migration 1->100

.fallbackToDestructiveMigration()

Having this in place sounds good to me. With this in place, we could do proper migrations just for beta/prod releases.

.fallbackToDestructiveMigration()

Having this in place sounds good to me. With this in place, we could do proper migrations just for beta/prod releases.

The discussed solution has already been implemented on the current master. Closing this issue, feel free to re-open if the issues comes up again.

I am facing the same issue but fallbackToDestructiveMigration() is not working. Whenever I upload data from database to my recyclerView it crashes
Is there a way to solve this by adding any dependancy or changing version number as the error suggests

(PS I'm. a beginner so I don't really know that much and desperately need help )

The reason for the actual problem is very clear in the error message. Quoting the relevant portion:

Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.

how to change this version number ??

@Gunin2001 IIUC, updating the version number shouldn't be necessary if fallbackToDestructiveMigration works properly. Where do you face this issue?

Was this page helpful?
0 / 5 - 0 ratings