3

I'm relying on an encrypted realm to store certain data in an app written in Swift. Sometimes I face a situation where I delete a given realm and create a new one to ensure that no data will persist between certain states.

I keep track of encryption keys myself, so there is a risk that I unintentionally attempt to decrypt a realm with a wrong encryption key, which raises the following exception:

libc++abi.dylib: terminating with uncaught exception of type realm::RealmFileException: Unable to open a realm at path '/path/to/private.realm': Realm file decryption failed.

Since this means that I have lost the original encryption key, essentially leaving this particular realm useless, I'd like to be able to delete the realm file and start over instead of crashing.

I create the realm as suggested by the docs:

do {
  var configuration = Realm.Configuration.defaultConfiguration
  configuration.encryptionKey = ...
  try Realm(configuration: configuration)
}
catch let error {

}

I've tried this and similar approaches to catch the NSException and return it to be handled by Swift code, but there doesn't seem to be an straight forward way to achieve this. Is it impossible, or am I approaching this incorrectly?

Community
  • 1
  • 1
Kasper Munck
  • 4,173
  • 2
  • 27
  • 50

2 Answers2

4

Your code should work. If the encryption key is wrong, entered the catch block. Then you can delete existing file and re-create Realm. Like the following:

var configuration = Realm.Configuration.defaultConfiguration
configuration.encryptionKey = getKey()
do {
    let realm = try Realm(configuration: configuration)
    ...
}
catch {
    try! NSFileManager().removeItemAtURL(configuration.fileURL!)
    let realm = try! Realm(configuration: configuration)
    ...
}

If you cannot catch the wrong encryption error, it might be using old Realm.framework. Please update the latest version of Realm.

kishikawa katsumi
  • 10,418
  • 1
  • 41
  • 53
  • Thanks for replying kishikawa. I just verified that we are using Realm 1.0.2 and Realm Swift 1.0.2, which are the newest version according to your docs. The exact code I use to create the realm can be viewed [here](https://gist.github.com/kaspermunck/9b1dcbf07773b22e109eefd552200e00) (more or less copied from the docs). – Kasper Munck Aug 10 '16 at 07:46
  • @Muncken I tested your gist code, and confirmed to enter catch clause. If the problem is reproducible, can you please send the project to help@realm.io to investigate? I worked at Realm. – kishikawa katsumi Aug 10 '16 at 08:01
  • I have isolated the code in scope in a separate project and reproduced the problem. I will forward that to you. Leaving this thread open for now. – Kasper Munck Aug 11 '16 at 09:27
4

It turns out the problem was caused by a bug in Realm, where deleteRealmIfMigrationNeeded = true when using encryption, caused the exception to be thrown, but impossible to catch.

From my (very helpful) correspondence with kishikawa katsumi:

The problem that unable to catch error is due to deleteRealmIfMigrationNeeded is true. It changes code flow unintentionally. It seems Realm's bug. We will fix soon.

For now, the only thing to do in my case is to set deleteRealmIfMigrationNeeded = false and handle this case manually. I have filed this issue to Realm.

Update: The issue should be resolved with this commit.

Kasper Munck
  • 4,173
  • 2
  • 27
  • 50