fix(db): v1.5.2 hotfix #2 — bump DB version after entity annotation changes#143
fix(db): v1.5.2 hotfix #2 — bump DB version after entity annotation changes#143
Conversation
Smoke install of the previous hotfix on a real device crashed with: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. Expected identity hash: 5c3585c27257d8b0a1a3119c4e50e1ac Found: 821e95d07068b708ea3b07e0d3311b0a Cause: Room computes its stored identity hash from entity definitions, not from the on-disk schema. The previous hotfix added @Index and @ColumnInfo annotations whose effect on the on-disk shape is zero (the migrations 1->8 already produced exactly that shape), but the entity definitions themselves changed, which means a new identity hash. Room refuses to open a v8 DB whose stored hash doesn't match the current v8 hash, even when the schema is byte-for-byte identical. Fix: bump @database version 8 -> 9 and add a no-op MIGRATION_8_9. This forces Room to refresh its bookkeeping (re-record the new identity hash) on the first open after upgrade. Fresh installs at v9 use the @entity declarations directly, no migrations run. For users who briefly opened v1.5.1 (and got the old hash written to disk), v1.5.2 will run MIGRATION_8_9, validate against the entity declarations (which now match the on-disk shape), pass validation, and record the new identity hash. No data loss.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 28 minutes and 43 seconds.Comment |
Smoke install of the previous patch on the same device crashed with
the same TableInfo mismatch as the original v1.5.1 crash, just from
the opposite direction. The on-disk DB has neither idx_tx_pending nor
walletId DEFAULT '', because the user installed v1.5.1 fresh — Room
created v8 directly from v1.5.1's broken entity declarations, which
declared neither.
Two distinct v8 shapes exist in the wild:
Path A — upgrade from v1.5.0: ran MIGRATION_2_3 (walletId DEFAULT '')
and MIGRATION_5_6 (idx_tx_pending). Both present.
Path B — fresh install on v1.5.1: schema came straight from broken
entities. Neither present.
The previous no-op MIGRATION_8_9 was sufficient for path A but left
path B mismatched against the v1.5.2 entity declarations.
This rewrite recreates transactions, balance_cache, and dao_cells with
the canonical column DEFAULT '' on walletId, and (re)creates
idx_tx_pending as a regular index (matching what the entity declares).
Idempotent against both paths: path A users get the same shape back,
path B users get the missing pieces.
|
Smoke #2 on same device: still crashed, this time with a TableInfo mismatch where the on-disk DB lacks Two divergent v8 shapes exist now:
Pushed Smoke install one more time after this lands. Sorry for the back-and-forth — this is the exact failure shape that #142 (real |
…) (#147) * test(db): walking-migration regression guard + Room schema export (#142) The pre-existing MigrationTest used Room.inMemoryDatabaseBuilder which creates the schema directly from the current entity declarations and never exercises Migration.migrate code paths. So when v1.5.1's entity declarations drifted from what the migrations produced, the in-memory test passed but real upgraders crashed at launch (#141, #143). Adds: 1. Room schema export (exportSchema = true + ksp arg pointing at app/schemas/). Generates a versioned JSON dump per @database version. v9 committed in this PR. Future schema drift becomes visible in PR diffs. 2. WalkingMigrationTest: bootstraps a SQLite file at v8 with a known historical shape, opens it via Room.databaseBuilder, and lets Room run MIGRATION_8_9 + validate the result against entity declarations. Two test methods cover the divergent v8 shapes that existed in the wild after v1.5.1: - Path A (upgrade-from-v1.5.0): walletId DEFAULT '' + partial idx_tx_pending already on disk. - Path B (fresh-install-on-v1.5.1): neither. Both must converge to v9 successfully. 3. Regression-guard test that registers a no-op MIGRATION_8_9 (what the first cut of #143 shipped) and asserts path B fails with the exact 'Migration didn't properly handle' exception that surfaced in production. Permanent in-codebase guard against the test losing its detection power. Note on scope: the JVM/Robolectric harness here covers the v8→v9 upgrade path because that is where the historical fork lives. Walking from v1 forward is harder without an exported schema for v1 and is tracked in #144 Phase 2 (instrumented MigrationTestHelper). * fix(ci): don't commit Room schema JSONs (kotlinx-serialization conflict) CI's clean build hit AbstractMethodError in Room's SchemaBundle.$serializer because Room 2.8.4's bundled kotlinx-serialization-core is binary-incompatible with the project's kotlinx-serialization-json:1.8.0 on a fresh classpath. Local builds didn't repro because of cached classloaders. When a schema JSON exists at the target version, Room's processor deserializes it to diff against the new export. With no JSON present, Room only writes a new one, no deserialize path, no crash. Workaround: don't commit the JSONs. They're still generated on every build (locally and in CI), they just don't get persisted. The walking-migration test doesn't depend on them — it validates against entity declarations directly. Trade-off lost: schema diffs aren't visible in PR review. We get them back when we either upgrade Room to a version compiled against kotlinx-serialization 1.8.x, or downgrade kotlinx-serialization-json to 1.7.x. Tracked alongside #142. * fix(ci): turn Room exportSchema off; track re-enable in #149 Same AbstractMethodError surfaced even after .gitignore'ing the JSONs: Room's deserialize path runs on every KSP cycle, not only when an existing schema file is present. The dep conflict between Room 2.8.4 and kotlinx-serialization 1.8.0 needs a real fix before exportSchema can be on. Reverts the @database exportSchema flag and the room.schemaLocation KSP arg. The walking-migration test under src/test/ still validates schema-vs-entity drift via Room's onMigrate path, so #142's regression-guard value is unaffected. Re-enabling tracked in #149.
Summary
Smoke install of the v1.5.2 build (PR #141) on a real device crashed with a different Room error than the original v1.5.1 crash:
```
Room cannot verify the data integrity. Looks like you've changed schema
but forgot to update the version number.
Expected identity hash: 5c3585c27257d8b0a1a3119c4e50e1ac
Found: 821e95d07068b708ea3b07e0d3311b0a
```
Root cause
Room computes its stored identity hash from the @Entity/@ColumnInfo/@Index declarations, not from the on-disk schema. The previous hotfix (#141) added `@Index(idx_tx_pending)` + `@ColumnInfo(defaultValue = "''")` to align the entity declarations with what migrations 1→8 already produced on disk. The on-disk schema didn't change at all, but the entity declarations did, so the identity hash changed.
Room enforces: any DB whose stored identity hash differs from the current entity-derived hash refuses to open, even when the schemas are byte-for-byte identical and the version number is the same.
Fix
The migration body is intentionally empty: the on-disk shape is already correct from migrations 1→8. The version bump alone is the mechanism Room provides for refreshing the stored identity hash.
Why this wasn't caught
Same root cause as #142 already tracks: `MigrationTest` uses `inMemoryDatabaseBuilder` which creates a fresh schema and never runs migrations or interacts with on-disk identity hashes. A real-device smoke install is currently the only way to catch identity-hash drift.
Test plan
Follow-up
#142 still tracks the permanent fix (real migration test using `MigrationTestHelper` with exported schemas). This identity-hash mismatch is exactly the regression that test would catch, so it strengthens the case for prioritising it.