Room livedata : crash on launch

Viewed 61

Recently I've decided to start using LiveData in my Room database by adding it to ado methods and then observing them in ViewModel, then even though I updated DB version after making all the changes and made a migration, it throws this error on emulator launch

2022-07-03 15:35:17.723 4866-4891/com.example... E/SQLiteLog: (1) statement aborts at 1: [ROLLBACK;] cannot rollback - no transaction is active
2022-07-03 15:35:17.724 4866-4891/com.example... E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
    Process: com.example..., PID: 4866
    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:920)
     Caused by: android.database.sqlite.SQLiteException: cannot rollback - no transaction is active (code 1 SQLITE_ERROR)
        at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
        at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:709)
        at android.database.sqlite.SQLiteSession.endTransactionUnchecked(SQLiteSession.java:441)
        at android.database.sqlite.SQLiteSession.endTransaction(SQLiteSession.java:403)
        at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:589)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:422)
        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:151)
        at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:112)
        at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:706)
        at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:483)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:526)
        at androidx.room.util.DBUtil.query(DBUtil.java:86)
        at com.example...data.database.NoteDao_Impl$16.call(NoteDao_Impl.java:723)
        at com.example...data.database.NoteDao_Impl$16.call(NoteDao_Impl.java:720)
        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:920) 

My dao code :

@Dao
interface NoteDao {

    @Delete
    fun deleteFolder(folder: Folder)

    @Query("UPDATE Note SET isStarred = :state WHERE id = :id")
    fun updateNoteChecked(id : Int, state : Boolean)

    @Query("DELETE FROM Note WHERE id = :id")
    fun deleteNoteById(id : Int)

    @Query("SELECT * FROM Note WHERE id = :id")
    fun getNoteById(id : Int) : Note

    @Query("SELECT title FROM Folder WHERE id = :id")
    fun getFolderTitleById(id : Int) : String

    @Query("SELECT * FROM folder WHERE id = :id")
    fun getFolderById(id : Int) : Folder

    @Query("UPDATE Folder SET title = :title WHERE id = :id")
    fun updateFolderTitle(id : Int, title : String)

    @Query("SELECT * FROM Folder WHERE id = :id")
    fun getFolderWithNotesByFolderId(id : Int) : FolderWithNotes

    @Query("SELECT * FROM Note WHERE folderId = :id ORDER BY isStarred")
    fun getNotesByFolderId(id : Int) : LiveData<List<Note>>

    @Query("SELECT * FROM note WHERE content LIKE :query ORDER BY isStarred")
    fun searchAllNotes(query : String?) : LiveData<List<Note>>

    @Query("SELECT * FROM note WHERE folderId = :id AND content LIKE :query ORDER BY isStarred" )
    fun searchNotesByFolderId(query : String?, id : Int) : LiveData<List<Note>>

    @Query("SELECT * FROM Note ORDER BY isStarred")
    fun getAllNotes() : LiveData<List<Note>>

    @Query("SELECT * FROM  Folder WHERE id = :id")
    fun getFolderWithNotes(id : Int) : List<FolderWithNotes>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertFolder(folder : Folder)

    @Query("SELECT * FROM Folder")
    fun getAllFolders() : LiveData<List<Folder>>

    @Query("UPDATE folder SET noteCount = noteCount + 1 WHERE id = :id")
    fun updateOnInsertNote(id : Int)

    @Query("UPDATE folder SET noteCount = noteCount - 1 WHERE id = :id")
    fun updateOnDeleteNote(id : Int)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertNote(note : Note)

    @Delete
    suspend fun deleteNote(note : Note)
}

Database class :

@Database(entities = [Note::class, Folder::class] , version =  11 )
abstract class NoteDatabase : RoomDatabase() {
    abstract fun NoteDao() : NoteDao
}

Data base hilt provide method :

@Provides
    @Singleton
    fun provideNoteDatabase(app : Application) : NoteDatabase{
        return Room.databaseBuilder(
            app ,
            NoteDatabase::class.java,
            "notes",

        ).fallbackToDestructiveMigration()
            .addCallback(DatabaseCallback())
            .build()
    }
1 Answers

As per my comment, I suspect that the issue is within the callback (DatabaseCallback) and probably in the overidden onOpen method.

The reasoning is that the trace shows:-

  • that you have issued a query as per at androidx.room.RoomDatabase.query(RoomDatabase.java:526)
  • that this successfully opens the database as per at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316) -and then appears to end a transaction (without committing the transaction). As Room is proven, then the most likely issue is that an attempt is being made to end a transaction when no transaction has been started and thus, due to the lack of the commit, there is nowhere/nothing to rollback to.
Related