# android.database.sqlite.SQLiteException: Cannot read from cursor: column 'timestamp' has type TEXT but expected INTEGER (code 0)

- **ID:** `android/room-migration-ambiguous-column-type`
- **Domain:** android
- **Category:** data_error
- **Verification:** ai_generated
- **Fix Rate:** 87%

## Root Cause

Room migration script altered the schema without converting existing data types, causing a mismatch between the expected SQLite affinity (INTEGER) and the actual stored type (TEXT) in the column.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| Room 2.6.1 | active | — | — |
| Android 12 (API 31) | active | — | — |
| Android 11 (API 30) | active | — | — |
| Room 2.5.2 | active | — | — |

## Workarounds

1. **Write a manual migration that converts TEXT to INTEGER using CAST. Example in migration: ALTER TABLE my_table ADD COLUMN timestamp_temp INTEGER; UPDATE my_table SET timestamp_temp = CAST(timestamp AS INTEGER); ALTER TABLE my_table DROP COLUMN timestamp; ALTER TABLE my_table RENAME COLUMN timestamp_temp TO timestamp;** (90% success)
   ```
   Write a manual migration that converts TEXT to INTEGER using CAST. Example in migration: ALTER TABLE my_table ADD COLUMN timestamp_temp INTEGER; UPDATE my_table SET timestamp_temp = CAST(timestamp AS INTEGER); ALTER TABLE my_table DROP COLUMN timestamp; ALTER TABLE my_table RENAME COLUMN timestamp_temp TO timestamp;
   ```
2. **Use @TypeConverter to handle both types in the DAO. Example: @TypeConverter public static Long fromTimestamp(String value) { return value == null ? null : Long.parseLong(value); }** (85% success)
   ```
   Use @TypeConverter to handle both types in the DAO. Example: @TypeConverter public static Long fromTimestamp(String value) { return value == null ? null : Long.parseLong(value); }
   ```

## Dead Ends

- **Delete app data and reinstall** — This only works for development but destroys user data in production. The underlying migration issue is not fixed. (80% fail)
- **Add fallbackToDestructiveMigration() to Room database builder** — This drops the entire database on migration failure, losing all user data. It's a nuclear option that doesn't fix the type mismatch. (90% fail)
