App Information
- App name: Easy Notes
- Package name:
com.kin.easynotes
- Version:
1.7-fdroid
- Version code:
14
- Issue type: Crash
- Android version: 9.0
Expected Behavior
The app should remain stable when the user deletes a note from the note editing page.
After the user confirms deletion, the app should return to the note home page automatically, and the deleted note should be removed from the note list.
Actual Behavior
The app crashes during or immediately after the note deletion flow.
After the note is deleted, the app still attempts to query the deleted note as a required non-null Note object. Since the query result is empty, an uncaught IllegalStateException is thrown, and Android terminates the app process.
Reproduction Steps
- Launch Easy Notes.
- Open an existing note and enter the note editing page.
- Open the more-options menu.
- Tap the
Delete menu item.
- Observe whether a delete confirmation dialog appears.
- Confirm the deletion.
- Observe whether the app returns to the note home page and whether the deleted note is removed from the list.
- The app crashes after the delete operation because the deleted note is queried as a non-null object.
Crash Log
05-22 14:09:10.817 E/AndroidRuntime( 9378): FATAL EXCEPTION: main
05-22 14:09:10.817 E/AndroidRuntime( 9378): Process: com.kin.easynotes, PID: 9378
05-22 14:09:10.817 E/AndroidRuntime( 9378): java.lang.IllegalStateException: The query result was empty, but expected a single row to return a NON-NULL object of type <com.kin.easynotes.domain.model.Note>.
05-22 14:09:10.817 E/AndroidRuntime( 9378): at n3.b.k(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:143)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at v2.d.s(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:211)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at v2.d.i(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:13)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at s2.b.g(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:24)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at p2.t.r(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:7)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at v2.b.s(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:39)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at k4.a.g(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:9)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at D4.L.run(r8-map-id-912d22bf732c793dd6ce0a61b7047cb26ee10a96c5724178ea06c7a01d102097:117)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
05-22 14:09:10.817 E/AndroidRuntime( 9378): at java.lang.Thread.run(Thread.java:764)
05-22 14:09:10.817 E/AndroidRuntime( 9378): Suppressed: I4.g: [A0{Cancelling}@65c9dc1, Dispatchers.Main.immediate]
05-22 14:09:10.820 W/ActivityManager( 1609): Force finishing activity com.kin.easynotes/.presentation.MainActivity
05-22 14:09:10.873 W/InputDispatcher( 1609): channel 'f5ca875 com.kin.easynotes/com.kin.easynotes.presentation.MainActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
05-22 14:09:10.873 E/InputDispatcher( 1609): channel 'f5ca875 com.kin.easynotes/com.kin.easynotes.presentation.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
05-22 14:09:10.874 I/WindowManager( 1609): WIN DEATH: Window{f5ca875 u0 com.kin.easynotes/com.kin.easynotes.presentation.MainActivity}
05-22 14:09:10.874 W/InputDispatcher( 1609): Attempted to unregister already unregistered input channel 'f5ca875 com.kin.easynotes/com.kin.easynotes.presentation.MainActivity (server)'
05-22 14:09:10.884 I/ActivityManager( 1609): Process com.kin.easynotes (pid 9378) has died: vis +99TOP
05-22 14:09:10.886 W/SurfaceFlinger( 1467): Attempting to set client state on removed layer: com.kin.easynotes/com.kin.easynotes.presentation.MainActivity#0
05-22 14:09:10.886 W/SurfaceFlinger( 1467): Attempting to destroy on removed layer: com.kin.easynotes/com.kin.easynotes.presentation.MainActivity#0
Analysis
The crash is caused by a database query that expects exactly one non-null note object, but the query returns no rows:
java.lang.IllegalStateException:
The query result was empty, but expected a single row to return a NON-NULL object of type <com.kin.easynotes.domain.model.Note>.
This is typical of a Room DAO or repository method whose return type is declared as a non-null Note, while the database state can legally contain no matching row.
The visible trigger is the note deletion flow:
Open note editing page
Open more menu
Tap Delete
Confirm deletion
After the note is deleted, the app should navigate away from the editing page and stop observing or querying that deleted note. However, the stack trace indicates that the app still performs a query for the same note and expects a non-null result.
The relevant stack trace includes the app/database flow before the exception reaches the coroutine execution path:
n3.b.k
v2.d.s
v2.d.i
s2.b.g
p2.t.r
v2.b.s
k4.a.g
D4.L.run
The suppressed coroutine context shows that this failure is associated with a main-dispatcher coroutine:
Suppressed: I4.g: [A0{Cancelling}@65c9dc1, Dispatchers.Main.immediate]
This means the empty query result is not handled as a normal post-deletion state. Instead, it propagates as an uncaught exception, causing Android to force-finish the main activity:
Force finishing activity com.kin.easynotes/.presentation.MainActivity
Process com.kin.easynotes (pid 9378) has died
The root cause is that the app treats a note record as always existing even after the user deletes it. The delete flow should handle the empty result case or navigate away before continuing to observe/query the deleted note.
App Information
com.kin.easynotes1.7-fdroid14Expected Behavior
The app should remain stable when the user deletes a note from the note editing page.
After the user confirms deletion, the app should return to the note home page automatically, and the deleted note should be removed from the note list.
Actual Behavior
The app crashes during or immediately after the note deletion flow.
After the note is deleted, the app still attempts to query the deleted note as a required non-null
Noteobject. Since the query result is empty, an uncaughtIllegalStateExceptionis thrown, and Android terminates the app process.Reproduction Steps
Deletemenu item.Crash Log
Analysis
The crash is caused by a database query that expects exactly one non-null note object, but the query returns no rows:
This is typical of a Room DAO or repository method whose return type is declared as a non-null
Note, while the database state can legally contain no matching row.The visible trigger is the note deletion flow:
After the note is deleted, the app should navigate away from the editing page and stop observing or querying that deleted note. However, the stack trace indicates that the app still performs a query for the same note and expects a non-null result.
The relevant stack trace includes the app/database flow before the exception reaches the coroutine execution path:
The suppressed coroutine context shows that this failure is associated with a main-dispatcher coroutine:
This means the empty query result is not handled as a normal post-deletion state. Instead, it propagates as an uncaught exception, causing Android to force-finish the main activity:
The root cause is that the app treats a note record as always existing even after the user deletes it. The delete flow should handle the empty result case or navigate away before continuing to observe/query the deleted note.