ankidroid / Anki-Android

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.
GNU General Public License v3.0
8.74k stars 2.24k forks source link

NoteEditor: Crashes when tapping 'add' too much: `BackendDbFileTooOldException`: called `Result::unwrap()` on an `Err` value: PoisonError { .. } #17375

Open david-allison opened 2 weeks ago

david-allison commented 2 weeks ago

https://ankidroid.org/acra/app/1/bug/254118/report/363d44c3-26f0-4667-b9f7-c03c6390670a

net.ankiweb.rsdroid.BackendException$BackendDbException$BackendDbFileTooOldException: called `Result::unwrap()` on an `Err` value: PoisonError { .. }
    at net.ankiweb.rsdroid.BackendException$BackendFatalError.<init>(BackendException.java:99)
    at net.ankiweb.rsdroid.BackendException$Companion.fromError(BackendException.kt:108)
    at net.ankiweb.rsdroid.BackendKt.unpackResult(Backend.kt:281)
    at net.ankiweb.rsdroid.BackendKt.access$unpackResult(Backend.kt:1)
    at net.ankiweb.rsdroid.Backend.runMethodRaw$lambda$1(Backend.kt:118)
    at net.ankiweb.rsdroid.Backend.withBackend(Backend.kt:131)
    at net.ankiweb.rsdroid.Backend.runMethodRaw(Backend.kt:117)
    at anki.backend.GeneratedBackend.getCurrentDeckRaw(GeneratedBackend.kt:537)
    at anki.backend.GeneratedBackend.getCurrentDeck(GeneratedBackend.kt:542)
    at com.ichi2.libanki.Decks.getCurrentId(Decks.java:455)
    at com.ichi2.libanki.Decks.selected(Decks.java:483)
    at com.ichi2.libanki.Decks.current(Decks.java:458)
    at com.ichi2.libanki.Notetypes.current(Notetypes.java:153)
    at com.ichi2.libanki.Notetypes.current$default(Notetypes.java:151)
    at com.ichi2.anki.NoteEditor.setNote(NoteEditor.kt:2149)
    at com.ichi2.anki.NoteEditor.refreshNoteData(NoteEditor.kt:2142)
    at com.ichi2.anki.NoteEditor.onNoteAdded(NoteEditor.kt:1097)
    at com.ichi2.anki.NoteEditor.saveNoteWithProgress(NoteEditor.kt:1128)
    at com.ichi2.anki.NoteEditor.access$saveNoteWithProgress(NoteEditor.kt:198)
    at com.ichi2.anki.NoteEditor$saveNoteWithProgress$1.invokeSuspend(NoteEditor.kt)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
    at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:65)
    at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:371)
    at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith$default(DispatchedContinuation.kt:274)
    at kotlinx.coroutines.DispatchedCoroutine.afterResume(Builders.common.kt:257)
    at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:99)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loopOnce(Looper.java:232)
    at android.os.Looper.loop(Looper.java:317)
    at android.app.ActivityThread.main(ActivityThread.java:8592)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
    Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [p0{Cancelling}@5da7f05, Dispatchers.Main.immediate]

--------- beginning of main
11-07 13:24:00.523 I/AnkiDroid(29676): Timber config: PRODUCTION
11-07 13:24:00.523 I/AnkiDroid(29676): initialize()
11-07 13:24:00.634 I/AnkiDroid(29676): Not participating in analytics sample (sample percentage vs random: 10 53)
11-07 13:24:00.634 I/AnkiDroid(29676): setOptIn(): from false to false
11-07 13:24:00.634 I/AnkiDroid(29676): Participating in analytics sample (sample percentage vs random: 10 7)
11-07 13:24:00.641 I/AnkiDroid(29676): Creating notification channel with id/name: General Notifications/AnkiDroid
11-07 13:24:00.642 I/AnkiDroid(29676): Creating notification channel with id/name: Synchronization/Synchronization
11-07 13:24:00.642 I/AnkiDroid(29676): Creating notification channel with id/name: Global Reminders/Cards due
11-07 13:24:00.642 I/AnkiDroid(29676): Creating notification channel with id/name: Deck Reminders/Reminders
11-07 13:24:00.645 I/AnkiDroid(29676): AnkiDroidApp: Starting Services
11-07 13:24:00.645 W/AnkiDroid(29676): AnkiDroidApp/ BootService - unexpected action received, ignoring: null
11-07 13:24:00.661 I/AnkiDroid(29676): IntentHandler::onCreate
11-07 13:24:00.661 I/AnkiDroid(29676): Setting theme to BLACK
11-07 13:24:00.670 I/AnkiDroid(29676): Launching DeckPicker
11-07 13:24:00.740 I/AnkiDroid(29676): AnkiDroid Version = 2.19.1 (6953d60532ee2762d29b06fd1d76e69203ad8455)
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Backend Version = 0.1.43-anki24.06.3 (24.06.3 d678e39350a2d243242a69f4e22f5192b04398f2)
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Android Version = 14 (SDK 34)
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): ProductFlavor = play
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Manufacturer = Google
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Model = Pixel 7a
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Hardware = lynx
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Webview User Agent = Mozilla/5.0 (Linux; Android 14; Pixel 7a Build/AP2A.240905.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.86 Mobile Safari/537.36
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): ACRA UUID = 86e429e0-d254-493e-83b0-e1732345d970
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): FSRS = 0.6.4 (Enabled: null)
11-07 13:24:00.740 I/AnkiDroid(29676): 
11-07 13:24:00.740 I/AnkiDroid(29676): Crash Reports Enabled = true
11-07 13:24:00.746 I/AnkiDroid(29676): Setting theme to BLACK
11-07 13:24:00.750 I/AnkiDroid(29676): DeckPicker::onCreate
11-07 13:24:00.795 I/AnkiDroid(29676): (Re)opening Database: /storage/emulated/0/Android/data/com.ichi2.anki/files/AnkiDroid/collection.anki2
11-07 13:24:00.810 I/AnkiDroid(29676): No startup screens required
11-07 13:24:00.815 I/AnkiDroid(29676): isLegacyStorage(): current dir: /storage/emulated/0/Android/data/com.ichi2.anki/files/AnkiDroid
11-07 13:24:00.815 I/AnkiDroid(29676): scoped external dirs: /storage/emulated/0/Android/data/com.ichi2.anki/files
11-07 13:24:00.815 I/AnkiDroid(29676): scoped internal dir: /data/user/0/com.ichi2.anki/files
11-07 13:24:00.815 I/AnkiDroid(29676): isLegacyStorage(): false
11-07 13:24:00.821 I/AnkiDroid(29676): DeckPicker::onStart
11-07 13:24:00.834 I/AnkiDroid(29676): DeckPicker::onResume
11-07 13:24:00.897 I/AnkiDroid(29676): Updating deck list UI
11-07 13:24:00.908 I/AnkiDroid(29676): deck filter: 38 (null)
11-07 13:24:01.283 I/AnkiDroid(29676): IntentHandler::onDestroy
11-07 13:24:03.266 I/AnkiDroid(29676): Navigating to card browser
11-07 13:24:03.288 I/AnkiDroid(29676): DeckPicker::onPause
11-07 13:24:03.294 I/AnkiDroid(29676): Setting theme to BLACK
11-07 13:24:03.295 I/AnkiDroid(29676): CardBrowser::onCreate
11-07 13:24:03.296 I/AnkiDroid(29676): isLegacyStorage(): current dir: /storage/emulated/0/Android/data/com.ichi2.anki/files/AnkiDroid
11-07 13:24:03.296 I/AnkiDroid(29676): scoped external dirs: /storage/emulated/0/Android/data/com.ichi2.anki/files
11-07 13:24:03.296 I/AnkiDroid(29676): scoped internal dir: /data/user/0/com.ichi2.anki/files
11-07 13:24:03.296 I/AnkiDroid(29676): isLegacyStorage(): false
11-07 13:24:03.307 I/AnkiDroid(29676): isLegacyStorage(): current dir: /storage/emulated/0/Android/data/com.ichi2.anki/files/AnkiDroid
11-07 13:24:03.307 I/AnkiDroid(29676): scoped external dirs: /storage/emulated/0/Android/data/com.ichi2.anki/files
11-07 13:24:03.307 I/AnkiDroid(29676): scoped internal dir: /data/user/0/com.ichi2.anki/files
11-07 13:24:03.307 I/AnkiDroid(29676): isLegacyStorage(): false
11-07 13:24:03.312 I/AnkiDroid(29676): CardBrowser::onStart
11-07 13:24:03.314 I/AnkiDroid(29676): CardBrowser::onResume
11-07 13:24:03.335 I/AnkiDroid(29676): setting deck: 1689772716209
11-07 13:24:03.352 I/AnkiDroid(29676): initCompleted
11-07 13:24:03.368 I/AnkiDroid(29676): CardBrowser:: Completed searchCards() Successfully
11-07 13:24:03.858 I/AnkiDroid(29676): DeckPicker::onStop
11-07 13:24:03.860 I/AnkiDroid(29676): DeckPicker::onSaveInstanceState
11-07 13:24:03.950 I/AnkiDroid(29676): CardBrowser::U::onAttach
11-07 13:24:03.950 I/AnkiDroid(29676): CardBrowser::U::onCreate
11-07 13:24:03.978 I/AnkiDroid(29676): CardBrowser::U::onStart
11-07 13:24:03.978 I/AnkiDroid(29676): CardBrowser::U::onResume
11-07 13:24:06.050 I/AnkiDroid(29676): setting deck: 1695476713202
11-07 13:24:06.077 I/AnkiDroid(29676): CardBrowser:: Completed searchCards() Successfully
11-07 13:24:06.189 I/AnkiDroid(29676): CardBrowser::U::onPause
11-07 13:24:06.189 I/AnkiDroid(29676): CardBrowser::U::onStop
11-07 13:24:06.189 I/AnkiDroid(29676): CardBrowser::U::onViewDestroyed
11-07 13:24:06.189 I/AnkiDroid(29676): CardBrowser::U::onDestroy
11-07 13:24:06.189 I/AnkiDroid(29676): CardBrowser::U::onDetach
11-07 13:24:06.737 I/AnkiDroid(29676): CardBrowser::U::onAttach
11-07 13:24:06.737 I/AnkiDroid(29676): CardBrowser::U::onCreate
11-07 13:24:06.758 I/AnkiDroid(29676): CardBrowser::U::onStart
11-07 13:24:06.758 I/AnkiDroid(29676): CardBrowser::U::onResume
11-07 13:24:08.434 I/AnkiDroid(29676): setting deck: 1687346297103
11-07 13:24:08.465 I/AnkiDroid(29676): CardBrowser::U::onPause
11-07 13:24:08.465 I/AnkiDroid(29676): CardBrowser::U::onStop
11-07 13:24:08.465 I/AnkiDroid(29676): CardBrowser::U::onViewDestroyed
11-07 13:24:08.465 I/AnkiDroid(29676): CardBrowser::U::onDestroy
11-07 13:24:08.465 I/AnkiDroid(29676): CardBrowser::U::onDetach
11-07 13:24:08.474 I/AnkiDroid(29676): CardBrowser:: Completed searchCards() Successfully
11-07 13:24:08.980 I/AnkiDroid(29676): CardBrowser::onPause
11-07 13:24:08.988 I/AnkiDroid(29676): Setting theme to BLACK
11-07 13:24:08.989 I/AnkiDroid(29676): SingleFragmentActivity::onCreate
11-07 13:24:08.990 I/AnkiDroid(29676): isLegacyStorage(): current dir: /storage/emulated/0/Android/data/com.ichi2.anki/files/AnkiDroid
11-07 13:24:08.990 I/AnkiDroid(29676): scoped external dirs: /storage/emulated/0/Android/data/com.ichi2.anki/files
11-07 13:24:08.990 I/AnkiDroid(29676): scoped internal dir: /data/user/0/com.ichi2.anki/files
11-07 13:24:08.990 I/AnkiDroid(29676): isLegacyStorage(): false
11-07 13:24:08.992 I/AnkiDroid(29676): SingleFragmentActivity::onStart
11-07 13:24:08.992 I/AnkiDroid(29676): SingleFragmentActivity::a7::onAttach
11-07 13:24:08.993 I/AnkiDroid(29676): SingleFragmentActivity::a7::onCreate
11-07 13:24:09.016 I/AnkiDroid(29676): onCollectionLoaded() Edit note activity successfully started in add card mode with node id 0
11-07 13:24:09.019 I/AnkiDroid(29676): SingleFragmentActivity::a7::onViewCreated
11-07 13:24:09.020 I/AnkiDroid(29676): SingleFragmentActivity::a7::onStart
11-07 13:24:09.022 I/AnkiDroid(29676): SingleFragmentActivity::onResume
11-07 13:24:09.022 I/AnkiDroid(29676): SingleFragmentActivity::a7::onResume
11-07 13:24:09.575 I/AnkiDroid(29676): CardBrowser::onStop
11-07 13:24:09.578 I/AnkiDroid(29676): CardBrowser::onSaveInstanceState
11-07 13:24:18.196 I/AnkiDroid(29676): NoteEditor:: Save note button pressed
11-07 13:24:18.197 I/AnkiDroid(29676): NoteEditor:: Save note button pressed
11-07 13:24:18.212 I/AnkiDroid(29676): NoteEditor:: Save note button pressed
david-allison commented 2 weeks ago

Also note that the user spam-clicked 'save', which may have caused an issue

https://github.com/ankitects/anki/blob/7f5e0810145c3067f0345651af638dad790c56e5/rslib/src/storage/sqlite.rs#L425-L426

david-allison commented 2 weeks ago

Reproduced by spamming adding text and pressing 'add' on the Note Editor

BUT, this shows a BackendFatalError

https://ankidroid.org/acra/app/1/bug/254298/report/56093667-1aad-4306-adb2-32ef100d6a6b

criticalAY commented 2 weeks ago

The same Fatal error can't get the BackendDbFileTooOldException

davidjoeressen commented 5 days ago

I think that might be my report so to add a bit of context. The touchscreen in my smartphone is kinda jittery(?), so it often registers one tap as multiple ones. So it is like spam clicking, but really fast. Sometimes it shows the error message that the front of the card must not be empty and sometimes it completely crashes the app.

mikehardy commented 5 days ago

Thanks for the context @davidjoeressen, much appreciated. Still seems like something we should be able to handle, for instance any UI elements we have that cause asynchronous actions (like, "add" or "save" or anything that touches the database) should be disabled as the first step in performing the action, and only re-enabled when the action is completed (successfully or not). So double-tapping shouldn't ever matter...

And of course, we shouldn't crash :-)