net.sqlcihper.database.SQLiteException:file is not a database:, while compiling:select count(*) from sqlite_master;

I use google room with SQLCipher for storing data for Android, but I always get the exception from bug report log as following:

“net.sqlcihper.database.SQLiteException:file is not a database:, while compiling:select count(*) from sqlite_master;”

1 Like

In our iOS App also this error is coming not every time but randomly.

We are executing following commands to get the ciper_version and making sure that we have a valid connection
Step 1: sqlite3_open
Step 2: sqlite3_exec(db, (const char*) “SELECT count(*) FROM sqlite_master;”, NULL, NULL, NULL)
Step 3: sqlite3_prepare_v2(db, “PRAGMA cipher_version;”, -1, &stmt, NULL)
Step 4: sqlite3_step(stmt)

But not getting SQLITE_OK on step 2.

Not only this error, we are experiencing following error on step 2. Using sqlite3_errmsg(db) to fetch the error

  • File is not a database (When DB is not encrypted)
  • SQL logic error (When DB is encrypted)
  • disk I/O error (When DB is not encrypted)

Please not that We are supporting on/off encryption in our app.

Please let me know if any other information needed.

Hey @krishan_kumar_Varshn

Thanks for your interest in SQLCipher and for posting to the discussion forum. The information you’ve provided is not enough to determine what could be causing the issue for you.

A couple of comments related to the information you provided:

  • You don’t mention where you provide a key for the database or how you are sourcing the key material
  • Frequently the File is not a database error indicates that you provided incorrect key material or that you provided key material for an unencrypted database
  • You mentioned that you are support on/off encryption. To encrypt a plaintext database or decrypt an encrypted database you should be using the sqlcipher_export() convenience function are you using this?
  • How are you determining whether encryption is active or not? You may want to read the first 16 bytes of the file to check for the magic string to determine whether the file is not encrypted: Database File Format

Hi @mmoore
Let me answer to all queries.

We store raw key in keychain, and based on the key’s availability we decide whether DB is in encrypted state or not, if it is in encrypted state then we execute commands in following order and if it is in plain state then the order I have already mentioned.

Step 1: sqlite3_open
Step2 : sqlite3_exec(db, (const char*)“PRAGMA cipher_plaintext_header_size=32”, NULL, NULL, NULL)
Step 3: sqlite3_exec(db, (const char*) [@“databaseKey” UTF8String], NULL, NULL, NULL)
Step 4: sqlite3_exec(db, (const char*) “SELECT count(*) FROM sqlite_master;”, NULL, NULL, NULL)
Step 5: sqlite3_prepare_v2(db, “PRAGMA cipher_version;”, -1, &stmt, NULL)
Step 6: sqlite3_step(stmt)

As I have already mentioned in both cases (encrypted and plain), “SELECT count(*) FROM sqlite_master;” is failing.

We will again check the flow in our code, but we are pretty sure that we give Key only for encrypted DB.

Yes, we are using sqlcipher_export function only, one thing I want to mention here is that while encrypting the DB we keep header in plain text only.
By executing PRAGMA destinationDB.cipher_plaintext_header_size = 32

No, right now we don’t read first 16 bytes to determine, but if there is key in keychain then DB is encrypted otherwise not.

You should be setting they key on the database (if it’s encrypted) prior to running any operations on it (i.e. cipher_plaintext_header_size).

Step 3: sqlite3_exec(db, (const char*) [@“databaseKey” UTF8String], NULL, NULL, NULL)

There are examples here of how to set the key, the syntax above doesn’t look like you’re using one of those (i.e. PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";)

You may want to review the cipher_plaintext_header_size documentation. As noted there, the application is responsible for providing the salt as well when using cipher_plaintext_header.

Hi, Sorry to say, but I did one mistake in previous message.
Yes we are providing password just after Step 1 by using sqlite3_key and Step 3 is actually
PRAGMA cipher_salt = \"%@\"
Really sorry about this.

So this is a case of encryption but we are getting error for plain DB also.

One more thing, we are making Connection with DB just after app launch in didFinishLaunchingWithOptions method. Infact this is first thing which we are doing in didFinishLaunchingWithOptions.

Could there be a case when the access to file. or sandbox is not yet released to our app’s process. Because these errors are random we are not getting everytime.

And really thanks for reply.

@krishan_kumar_Varshn

This points to some error in your application logic rather than any issues with SQLCipher.

Some recommendations:

  1. Attempt to extract the database from the application and verify it with a separate test application
  2. Create a standalone project which produces the issue
  3. Attempt to use a hard coded key within debug builds to see if you can reproduce the error there
  4. Purchase CipherCare support if you’d like assistance in debugging the issue further from us