Error re-creating DB after password change; started happening with 3.x upgrade

Error re-creating DB after password change; started happening with upgrade

We recently had to upgrade Couchbase Lite from 2.x to 3.2 due to Apple rejecting builds due to something our DevOps called bytecode.

Starting with this upgrade, our password change code has stopped working on iOS.

We’re using *.swift files but they’re using an @objc annotation, so I’m not certain which language s actually used.
I think this is a requirement for these functions to be exposed to react-native, which we use.

This code calls
Database.delete(withName: dbName)
and I tried to change to:
Database.delete(withName: dbName, inDirectory: directory)
I tried to use database.delete() too, but I couldn’t instantiate the database without the previous password.

None of these throw any error and the execution goes on as if they worked.
But then when we get to the following line, which should re-create the DB:
let database = try Database(name: dbName, config: config)
…we’re getting this error instead:
file is not a database (or encryption key is invalid/missing)

This has us suspecting that the database hasn’t actually been deleted and that the error comes because the code is trying to decrypt the old DB with the new password.

What could we try to fix this issue?

Note that we did try to use changeEncryptionKey before we settled for this approach, but we were not able to get it working properly. I wasn’t the one who worked on this so I don’t have more details.

Versions:

  • Server: 7.6.5
  • Sync: 3.2.4
  • Lite: 3.2

Umm… Can you give us a clue about what platform you are using? Is this Java? Swift? .NET? On what kind of device?

Apologies, I thought I had. We’re using *.swift files but they’re using an @objc annotation, so I’m not certain which language s actually used.

I’ve looked into this @objc annotation and it seems to be required for these functions to be exposed to react-native, which we use.

Since we’re able to get the path to the databases with DatabaseConfiguration().directory, would it be possible to work around this issue by manually deleting the database with the filesystem API? By the time we’re trying to delete the database, there is no active database connection because the user is not logged in.

Can you check if the database was in-fact deleted or not by using Database.exists(withName: ..., inDirectory: ...) ? It returns a Boolean.

You can use Database.delete(withName:, inDirectory:) to remove the encrypted database. The function just simply deletes the database file. However, please make sure the database is closed before delete otherwise an error will be thrown. Make sure that the function is called with the correct directory contained the database unless the default directory is used.

As @vlad.velicu suggested, you can debug the issue by using database.exists(withName:, inDirectory:) to check whether the database still exists or not.

I know the database was not being deleted because I could still find the folder in the file system.
For some reason, the function just stopped working for us after the upgrade.
It was not a matter of the database being in use; the user is not logged in when they do reset password.
I couldn’t find any way to do it “the right” way so, in the end, I had to go with manually deleting it with the filesystem API. I can’t say I love this solution.
This seems to work without issues and the customer has already approved the change, so it will be “permanent” until it breaks again or they request a change (we’re not allowed to do changes that have not been requested).

Was the database trying to be deleted a 2.x version database using 3.2 CBL? Or is this reproducible when the database is both created and deleted using 3.2?

The database was a 3.2 database.

To be more specific, the sync database was a 3.2.4 database migrated from 2.x.
But the lite database was replicated already as a 3.2 database.