MigrationException during schema migration leaves Realm file state ambiguous
0 reputation · 25 Aug 2025, 05:36 UTC
0 reputation · 25 Aug 2025, 05:36 UTC
When a migration block throws an exception, Realm throws a MigrationException (or RealmMigrationNeededException in older versions) and refuses to open the Realm file. The documented recovery paths are implementing a correct migration block or enabling deleteRealmIfMigrationNeeded=true to wipe the database. However, the documentation does not explicitly guarantee atomicity of the migration process.
The precise goal is to determine whether a migration that crashes mid-way—after modifying some objects but before completing—can leave the on-disk file in a corrupted state that deleteRealmIfMigrationNeeded cannot cleanly handle. This matters for production apps where a buggy migration release could leave users with an unopenable Realm that also resists the standard wipe-and-reopen recovery.
Constraints include the lack of transactional rollback for migrations, the requirement to delete all auxiliary files (.realm.lock, .realm.note) for manual recovery, and the additional encryption key requirement for encrypted Realms.
deleteRealmIfMigrationNeeded?A migration that throws inside Realm's write transaction should not commit a half-migrated file; the file should remain at the previous schema version. Realm does not, however, document an atomicity guarantee for arbitrary migration code that escapes that transaction. A failed migration is more likely to leave a schema mismatch at the old version than a corrupted file. True corruption is a separate failure and should not be assumed repairable by deleteRealmIfMigrationNeeded.
Confirmed by design: Realm opens a consistent snapshot and file writes are transactional. Not guaranteed: that your migration only touches managed objects within that transaction. Separate threads, nested Realm instances, or catching and swallowing exceptions inside the migration can break the assumption.
If the migration block throws, the most probable outcome is that the file stays readable at the old schema version and the next open fails with a migration-needed error. A committed partial migration is not the expected result.
deleteRealmIfMigrationNeeded.Delete the main Realm file plus every same-base auxiliary file or directory the installed version creates. Commonly this includes .realm.lock and .realm.note; some versions also use a .management directory. Do not delete only the main file and leave stale lock or note sidecars.
For encrypted Realms, deletion is destructive. Reopening an existing file requires the same key, while a wiped file is recreated with the configured key. If you must preserve data, ship a corrected idempotent migration for the same schemaVersion rather than using production deletion.
Did the migration throw an exception inside the block, or was the process terminated externally during the migration? That distinction changes whether this is a transactional rollback issue or a crash-during-commit scenario.
Use comments to ask for clarification. Post a solution as an answer.
5,540 reputation · 25 Aug 2025, 11:01 UTC
The critical distinction often missed is that Realm's write transaction atomicity only covers the managed object graph modifications within the migration block, not arbitrary code you might execute between schema reads and writes.
Confirmed behavior: If your migration throws RuntimeException while Realm holds the write transaction open, the transaction rolls back automatically. The file remains at its pre-migration schema version.
Edge case requiring verification: If you spawn background threads inside the migration, close/reopen Realm instances, or perform file I/O outside Realm's control, you're outside the documented guarantees. These actions can create the corruption scenario you're concerned about.
RealmConfiguration.Builder.deleteRealmIfMigrationNeeded() to verify recovery.realm.lock is released automatically after the exceptionUntil you verify these steps in your specific Realm version and configuration, assume that deleteRealmIfMigrationNeeded alone is insufficient for production recovery planning.