'Android Room Migration didn't properly handle

Through crashlytics I'm finding a crash event saying room did not handle the migration of one of my tables. Can anyone see what exactly could be wrong with my table? As far as i'm aware it's correct in terms of adding default values, and i've even done auto migrations with way previously without issues

 Fatal Exception: java.lang.IllegalStateException: Migration didn't properly handle: player_table(com.tapmax.football.model.PlayerModel).
 Expected:
TableInfo{name='player_table', columns={skillMoves=Column{name='skillMoves', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, playerName=Column{name='playerName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, pace=Column{name='pace', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, shooting=Column{name='shooting', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, defending=Column{name='defending', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, playerImageUrl=Column{name='playerImageUrl', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, dribbling=Column{name='dribbling', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, overall=Column{name='overall', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, passing=Column{name='passing', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, playerPosition=Column{name='playerPosition', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, value=Column{name='value', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, physic=Column{name='physic', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, playerNameUnaccented=Column{name='playerNameUnaccented', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, playerId=Column{name='playerId', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, playerPositionCategory=Column{name='playerPositionCategory', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultVal<truncated: 627 chars>
       at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:103)
       at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:183)
       at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:489)
       at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:387)
       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 com.tapmax.football.database.dao.DraftTeamDao_Impl.getDraftTeam(DraftTeamDao_Impl.java:110)
       at com.tapmax.football.viewmodel.BuildScreenViewModel$1.invokeSuspend(BuildScreenViewModel.kt:67)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Table: the fields from 'playerPosition' and down are the new fields i've added. I put an auto migration strategy in my database for these.

@Serializable
@Entity(tableName = "player_table")
data class PlayerModel(
    @PrimaryKey
    var playerId: String = "",
    var playerName: String = "",
    var playerNameUnaccented: String = "",
    var playerImageUrl: String = "https://cdn.sofifa.com/players/notfound_0_120.png",
    @ColumnInfo(defaultValue = "")
    var playerPosition: String = "",
    @ColumnInfo(defaultValue = "")
    var playerPositionCategory: String = "",
    @ColumnInfo(defaultValue = "")
    var overall: String = "",
    @ColumnInfo(defaultValue = "")
    var value: String = "",
    @ColumnInfo(defaultValue = "")
    var age: String = "",
    @ColumnInfo(defaultValue = "")
    var skillMoves: String = "",
    @ColumnInfo(defaultValue = "")
    var pace: String = "",
    @ColumnInfo(defaultValue = "")
    var shooting: String = "",
    @ColumnInfo(defaultValue = "")
    var passing: String = "",
    @ColumnInfo(defaultValue = "")
    var dribbling: String = "",
    @ColumnInfo(defaultValue = "")
    var defending: String = "",
    @ColumnInfo(defaultValue = "")
    var physic: String = ""

)

Database

    @Database(
    entities =
    [
        PlayerModel::class,
        SavedTeam::class,
        DraftTeam::class,
        Design::class
    ],
    version = 2,
    exportSchema = true,
    autoMigrations = [AutoMigration(from = 1, to = 2)]
)

@TypeConverters(
    BuildScreenStateConverter::class
)
abstract class LocalDatabase : RoomDatabase() {

    abstract fun playerDao(): PlayerDao
    abstract fun savedTeamDao(): SavedTeamDao
    abstract fun draftTeamDao(): DraftTeamDao
    abstract fun designDao(): DesignDao

    companion object {
        @Volatile
        private var INSTANCE: LocalDatabase? = null

        fun getDatabase(context: Context): LocalDatabase {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }

            synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    LocalDatabase::class.java,
                    "local_database"
                )
                    .fallbackToDestructiveMigration()
                    .build()
                INSTANCE = instance
                return instance
            }
        }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source