# Issue Migrating From android-database-sqlcipher:3.5.9 to sqlcipher-android:4.5.5

**URL:** <https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370>\
**Category:** SQLCipher\
**Created:** [April 3, 2024, 12:35pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370 "2024-04-03T12:35:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [April 3, 2024, 12:35pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/1 "2024-04-03T12:35:43Z")

</div>

Hello  
I am migrating from net.zetetic:android-database-sqlcipher:3.5.9 to net.zetetic:sqlcipher-android:4.5.5

My implementation looks like below.

private DatabaseHelper(Context context) {  
super(context, DBNAME, null, VERSION);  
this.context = context;  
}

```
@Override
public void onCreate(SQLiteDatabase db) {
	db.execSQL(CREATE_PERFORMANCE);
	db.execSQL(CREATE_TICKET);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	Log.w(Constants.tag, "Upgrading database from version " + oldVersion + " to " + newVersion
			+ ", which will destroy all old data");
	db.execSQL("DROP TABLE IF EXISTS ticket"); //
	db.execSQL("DROP TABLE IF EXISTS performance"); //
	onCreate(db);
}

public DatabaseHelper open() throws SQLException {
	System.loadLibrary("sqlcipher");
	database = this.getWritableDatabase();
	return this;
}

public SQLiteDatabase getDatabase() {
	if(database == null){
		System.loadLibrary("sqlcipher");
		database = getWritableDatabase();
	}
	return database;
}

```

I made changes after referring [SQLCipher for Android Migration - How to Convert Applications from android-database-sqlcipher to sqlcipher-android | Zetetic](https://www.zetetic.net/sqlcipher/sqlcipher-for-android-migration/)

but when getWritableDatabase() gets called , crashing with below message  
Caused by: android.database.sqlite.SQLiteException: file is not a database (code 26): , while compiling: PRAGMA journal\_mode

please help on this, I am stuck since few days.

---

<div class="post-metadata">

**Author:** ![mmoore](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/mmoore/32/858_2.png) [@mmoore](https://discuss.zetetic.net/u/mmoore)\
**Post date:** [April 3, 2024, 2:18pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/2 "2024-04-03T14:18:29Z")

</div>

Hi @Anshuman_Biswal

Thank you for your interest in SQLCipher and for posting to the discussion forum.

SQLCipher 3.x has different encryption settings than SQLCipher 4.x, so you’ll need to migrate your database(s) to use these new encryption settings (or open them in compatibility mode) as outlined in this post: [Upgrading to SQLCipher 4](https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283)

SQLCipher should properly migrate all your tables and database data when performing the migration, so you shouldn’t need to drop your tables and re-create them onUpgrade like you’re doing unless that’s an application requirement.

---

<div class="post-metadata">

**Author:** ![mmoore](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/mmoore/32/858_2.png) [@mmoore](https://discuss.zetetic.net/u/mmoore)\
**Post date:** [May 7, 2024, 7:19pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/4 "2024-05-07T19:19:17Z")

</div>

@Anshuman_Biswal

The API documentation for cipher\_migrate is here: [SQLCipher API - Full Database Encryption PRAGMAs, Functions, and Settings | Zetetic](https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_migrate)

You’ll want to follow the guidance mentioned in the API documentation for how to determine whether to perform the migration as it is expensive.

There’s an example of calling cipher\_migrate in the postKey hook here: [sqlcipher-android-tests/app/src/main/java/net/zetetic/tests/CipherMigrateTest.java at master · sqlcipher/sqlcipher-android-tests · GitHub](https://github.com/sqlcipher/sqlcipher-android-tests/blob/master/app/src/main/java/net/zetetic/tests/CipherMigrateTest.java)

From your code it looks like you’re hard coding a key value. We strongly recommend against doing that. There’s some information about Key Material and Selection, along with some technical guidance in these posts:

> [@SQLCipher Database Key Material and Selection](https://discuss.zetetic.net/t/sqlcipher-database-key-material-and-selection/25):
>
> By design, SQLCipher doesn’t perform permanent storage of the database password and key material. This provides maximum flexibility, allowing an application to provide key material from any combination of sources (e.g. user provided passphrase, key material on device, external hardware tokens, etc.). While this cleanly separates the management of the key material from the implementation of the database encryption, allowing SQLCipher to address the widest possible set of requirements and use cas…

> **[Technical Guidance: Using Random Values as SQLCipher Keys](https://www.zetetic.net/blog/2019/06/07/technical-guidance-using-random-values-as-sqlcipher-keys/)**
>
> Technical guidance on using random values as SQLCipher keys.

---

<div class="post-metadata">

**Author:** ![sebalz](https://avatars.discourse-cdn.com/v4/letter/s/bcef8e/32.png) [@sebalz](https://discuss.zetetic.net/u/sebalz)\
**Post date:** [June 5, 2024, 9:25am UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/5 "2024-06-05T09:25:15Z")

</div>

Hi, I’m trying to migrate from sqlcipher 3.5.9 to (4.5.4 or to 4.6.0).  
The starting db contained a custom page size “4096”

public CipherDBOpenHelper(@Nullable Context context, String password) {  
super(context, DATABASE\_NAME, null, DATABASE\_VERSION, new SQLiteDatabaseHook() {  
@Override  
public void preKey(SQLiteDatabase database) {  
database.execSQL("PRAGMA key = "+ password);  
database.execSQL(“PRAGMA cipher\_page\_size = 4096”);  
}

```
        @Override
        public void postKey(SQLiteDatabase database) {

        }
    });
}

```

From the documentation I understood that in this case i need to use the export function:

```
public static void migrateDb(String password) {
    SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
        @Override
        public void preKey(SQLiteDatabase database) {
        }
        @Override
        public void postKey(SQLiteDatabase database) {
            //database.execSQL("PRAGMA cipher_compatibility = 3;");
            database.execSQL("PRAGMA cipher_page_size = 4096;");
            database.execSQL("PRAGMA cipher_hmac_algorithm = HMAC_SHA1;");
            database.execSQL("PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;");
            try {
                database.rawExecSQL(String.format("ATTACH DATABASE '%s' AS history_log_new KEY '%s'",
                        dbNewFile.getAbsoluteFile(),password));
            }catch (Exception e){
                Log.e(DBTEST_LOG,"errore "+e);
            }

            database.rawExecSQL(String.format("SELECT sqlcipher_export('%s')","history_log_new"));
            database.rawExecSQL(String.format("DETACH DATABASE '%s'","history_log_new"));
        }
    };
    //create new db
    SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(dbNewFile.getPath(),password, null);
    database.close();
    //start export
    SQLiteDatabase databaseOld = SQLiteDatabase.openOrCreateDatabase(dbOldFile.getPath(),password,null,hook);
    databaseOld.close();

    //open new db
    database = SQLiteDatabase.openOrCreateDatabase(dbNewFile.getPath(), password, null);

```

I get an exception : File is not a database.

 ![Capture](https://us1.discourse-cdn.com/flex016/uploads/zetetic/original/2X/f/fd35601979cc39aec81fdf04139a11e365e33448.jpeg)

I did a series of tests and looked at all the examples you posted. I tried to do the migration starting from a db with default settings and using “cipher migration” and it works correctly. In my opinion the problem arises from the page size.

What am I doing wrong :-)?  
Thank you,

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [June 5, 2024, 3:48pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/6 "2024-06-05T15:48:25Z")

</div>

Hi @sebalz,

You don’t need to create the new database first, the `sqlcipher_export(...)` function will do that during the export. You need to open the old database using the hook, but also execute the following:

```auto
PRAGMA cipher_compatiblity = 3;
PRAGMA cipher_page_size = 4096;
ATTACH DATABASE 'history_log_new.db' as sqlcipher4 KEY 'YourPasswordHere';
SELECT sqlcipher_export('sqlcipher4');
DETACH DATABASE sqlcipher4;

```

This will allow `history_log_new.db` to be created with default SQLCipher 4 configuration settings.

---

<div class="post-metadata">

**Author:** ![sebalz](https://avatars.discourse-cdn.com/v4/letter/s/bcef8e/32.png) [@sebalz](https://discuss.zetetic.net/u/sebalz)\
**Post date:** [June 6, 2024, 8:40am UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/8 "2024-06-06T08:40:29Z")

</div>

Thank you. You solved my problem. I had read in a comment not to use “compatibility” when the original db uses custom settings.  
In any case there was a piece missing: “there was no need to create a new database”.  
Greetings

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [June 6, 2024, 2:03pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/9 "2024-06-06T14:03:37Z")

</div>

Hi @sebalz,

Excellent, glad to hear that addressed the issue.

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [June 19, 2024, 4:39pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/10 "2024-06-19T16:39:50Z")

</div>

Hello  
Now I am trying to update  
implementation ‘net.zetetic:android-database-sqlcipher:3.5.9’ to implementation ‘net.zetetic:android-database-sqlcipher:4.5.4’

My implementation is mentioned below.  
public DatabaseHelper open() throws SQLException {  
SQLiteDatabase.loadLibs(this.context);  
database = this.getWritableDatabase(Constants.api\_secret);  
return this;  
}

```
public SQLiteDatabase getDatabase() {
    if (database == null) {
        SQLiteDatabase.loadLibs(this.context);
        database = getWritableDatabase(Constants.api_secret);
    }
    return database;
}

```

private DatabaseHelper(Context context) {  
super(context, DBNAME, null, VERSION, new SQLiteDatabaseHook() {

```
        @Override
        public void preKey(SQLiteDatabase sqLiteDatabase) {

        }

        @Override
        public void postKey(SQLiteDatabase sqLiteDatabase) {
            try (Cursor cursor = sqLiteDatabase.rawQuery("PRAGMA cipher_migrate", null)) {
                // Check if migration was successful
                if (cursor != null && cursor.moveToFirst()) {
                    int result = cursor.getInt(0);
                    cursor.close();
                    if (result == 0) {
                        Log.d("DataBaseHelper", "migration is successful");
                    } else {
                        // Handle migration failure
                        throw new SQLiteException("Cipher migration failed");
                    }
                } else {
                    // Handle no result or cursor error
                    throw new SQLiteException("No result from PRAGMA cipher_migrate");
                }
            } catch (Exception e) {
                throw new SQLiteException("Error executing PRAGMA cipher_migrate", e);
            }
        }
    });
    this.context = context;
}

```

working fine but some times getting ANR.  
Can you please let me know based on below link  
postKey() implementation is correct or not( not sure why this change is causing ANR as log is printed - Migration is successful )?. Only for changing the version( 3.5.9 to 4.5.4) do I need to increase the db version?. Can you please help on this.

> [@Upgrading to SQLCipher 4](https://discuss.zetetic.net/t/upgrading-to-sqlcipher-4/3283):
>
> The recent release of [SQLCipher 4](https://www.zetetic.net/blog/2018/11/30/sqlcipher-400-release/) introduces many new performance and security enhancements for applications that use SQLCipher for secure local data storage. However, the introduction of new default algorithms, increased KDF iterations and a larger page size means that SQLCipher 4 will not open older databases by default. This document provides guidance on the upgrade options available to applications that have previously integrated SQLCipher versions 1 through 3. Option 1: Database File Migr…

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [June 24, 2024, 12:32pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/11 "2024-06-24T12:32:52Z")

</div>

Hello  
Can you please help on this.

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [June 24, 2024, 3:39pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/12 "2024-06-24T15:39:07Z")

</div>

Hi @Anshuman_Biswal,

Unfortunately, there is not enough information to determine why you are occasionally receiving an ANR. Because the `cipher_migrate` process will have to rewrite each page within the database, the size of each database may impact the overall time to complete the process. You should make sure you are not performing this operation on the main UI thread as it may block.

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [June 24, 2024, 3:45pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/13 "2024-06-24T15:45:06Z")

</div>

Can you please let me know  
postKey() implementation is correct or not?  
private DatabaseHelper(Context context) {  
super(context, DBNAME, null, VERSION, new SQLiteDatabaseHook() {  
@Override  
public void preKey(SQLiteDatabase sqLiteDatabase) {

```
    }

    @Override
    public void postKey(SQLiteDatabase sqLiteDatabase) {
        try (Cursor cursor = sqLiteDatabase.rawQuery("PRAGMA cipher_migrate", null)) {
            // Check if migration was successful
            if (cursor != null && cursor.moveToFirst()) {
                int result = cursor.getInt(0);
                cursor.close();
                if (result == 0) {
                    Log.d("DataBaseHelper", "migration is successful");
                } else {
                    // Handle migration failure
                    throw new SQLiteException("Cipher migration failed");
                }
            } else {
                // Handle no result or cursor error
                throw new SQLiteException("No result from PRAGMA cipher_migrate");
            }
        } catch (Exception e) {
            throw new SQLiteException("Error executing PRAGMA cipher_migrate", e);
        }
    }
});
this.context = context;

```

}

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [June 24, 2024, 4:40pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/14 "2024-06-24T16:40:10Z")

</div>

Hi @Anshuman_Biswal,

Yes, the usage of `PRAGMA cipher_migrate` within your `postKey` event looks good. Checking for a value of `0` to determine success is correct.

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [June 25, 2024, 3:28pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/15 "2024-06-25T15:28:33Z")

</div>

unfortunately I am getting below crash.  
@Override  
public void postKey(SQLiteDatabase sqLiteDatabase) {  
Executors.newSingleThreadExecutor().execute(new Runnable() {  
@Override  
public void run() {  
try (Cursor cursor = sqLiteDatabase.rawQuery(“PRAGMA cipher\_migrate”, null)) {  
// Check if migration was successful  
if (cursor != null && cursor.moveToFirst()) {  
int result = cursor.getInt(0);  
cursor.close();  
if (result == 0) {  
Log.d(“DataBaseHelper”, “migration is successful”);  
} else {  
// Handle migration failure  
throw new SQLiteException(“Cipher migration failed”);  
}  
} else {  
// Handle no result or cursor error  
throw new SQLiteException(“No result from PRAGMA cipher\_migrate”);  
}  
} catch (Exception e) {  
throw new SQLiteException(“Error executing PRAGMA cipher\_migrate”, e);  
}  
}  
});  
}  
});

=================

FATAL EXCEPTION: AsyncTask #2  
Process:  
java.lang.RuntimeException: An error occurred while executing doInBackground()  
at android.os.AsyncTask$4.done(AsyncTask.java:415)  
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:381)  
at java.util.concurrent.FutureTask.setException(FutureTask.java:250)  
at java.util.concurrent.FutureTask.run(FutureTask.java:269)  
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)  
Caused by: android.database.sqlite.SQLiteException: unable to close due to unfinalized statements or unfinished backups: sqlite3\_close() failed  
at net.sqlcipher.database.SQLiteDatabase.dbclose(Native Method)  
at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(SQLiteDatabase.java:2635)  
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1250)  
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1325)  
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:167)  
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:136)  
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)  
at android.os.AsyncTask$3.call(AsyncTask.java:394)  
at java.util.concurrent.FutureTask.run(FutureTask.java:264)  
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)  
2024-06-25 20:39:06.126 4166-4585 AndroidRuntime E FATAL EXCEPTION: pool-11-thread-1  
Process:  
android.database.sqlite.SQLiteException: Error executing PRAGMA cipher\_migrate  
at  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)  
Caused by: android.database.sqlite.SQLiteException: Cipher migration failed

```
                                                                                                	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
                                                                                                	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) 
                                                                                                	at java.lang.Thread.run(Thread.java:1012)

```

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [June 25, 2024, 9:57pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/16 "2024-06-25T21:57:31Z")

</div>

It look like you’re using try-with-resources, but also explicitly closing the cursor. If you remove the explicit call to close on the cursor does it go away? Is your AsyncTask doing anything else with the connection?

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [June 26, 2024, 2:57am UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/17 "2024-06-26T02:57:45Z")

</div>

If I remove cursor.close() , still it crashes ☹

there are 2 FATAL EXCEPTIONS  
**One during migration and another during clearTable()**

2024-06-26 08:06:54.353 13645-13769 AndroidRuntime com.ticke.android.app E FATAL EXCEPTION: AsyncTask #1  
Process: com.ticke.android.app, PID: 13645  
java.lang.RuntimeException: An error occurred while executing doInBackground()  
at android.os.AsyncTask$4.done(AsyncTask.java:415)  
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:381)  
at java.util.concurrent.FutureTask.setException(FutureTask.java:250)  
at java.util.concurrent.FutureTask.run(FutureTask.java:269)  
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)  
Caused by: android.database.sqlite.SQLiteException: unable to close due to unfinalized statements or unfinished backups: sqlite3\_close() failed  
at net.sqlcipher.database.SQLiteDatabase.dbclose(Native Method)  
at net.sqlcipher.database.SQLiteDatabase.openDatabaseInternal(SQLiteDatabase.java:2635)  
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1250)  
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1325)  
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:167)  
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:136)  
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)  
at **com.ticke.android.app.common.services.DatabaseHelper.getDatabase(DatabaseHelper.java:124)**  
at **com.ticke.android.app.common.services.DatabaseHelper.clearTables(DatabaseHelper.java:130)**  
at**com.ticke.android.app.common.services.DatabaseHelper$StoreUserTicketListTask.doInBackground(DatabaseHelper.java:146)**  
at **com.ticke.android.app.common.services.DatabaseHelper$StoreUserTicketListTask.doInBackground(DatabaseHelper.java:140)**  
at android.os.AsyncTask$3.call(AsyncTask.java:394)  
at java.util.concurrent.FutureTask.run(FutureTask.java:264)  
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)

===============================================================  
2024-06-26 08:06:54.356 13645-13770 AndroidRuntime com.ticke.android.app E FATAL EXCEPTION: pool-11-thread-1  
Process: com.ticke.android.app, PID: 13645  
android.database.sqlite.SQLiteException: Error executing PRAGMA cipher\_migrate  
at **com.ticke.android.common.services.DatabaseHelper$1$1.run(DatabaseHelper.java:91)**  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)  
Caused by: android.database.sqlite.SQLiteException: Cipher migration failed  
at com.ticke.android.common.services.DatabaseHelper$1$1.run(DatabaseHelper.java:84)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)  
at java.lang.Thread.run(Thread.java:1012)

**Inside asyncTask first we are calling**  
**clearTables()**  
public void clearTables() {  
getDatabase().execSQL(“delete from ticket”);  
getDatabase().execSQL(“delete from performance”);  
}

public SQLiteDatabase getDatabase() {  
if (database == null) {  
SQLiteDatabase.loadLibs(this.context);  
database = getWritableDatabase(Constants.api\_secret); // this is the last call from app’s class DatabaseHelper before crash.  
}  
return database;  
}

**postKey() code remains same , but removed cursor.close()**

@Override  
public void postKey(SQLiteDatabase sqLiteDatabase) {  
Executors.newSingleThreadExecutor().execute(new Runnable() {  
@Override  
public void run() {  
try (Cursor cursor = sqLiteDatabase.rawQuery(“PRAGMA cipher\_migrate”, null)) {  
// Check if migration was successful  
if (cursor != null && cursor.moveToFirst()) {  
int result = cursor.getInt(0);  
if (result == 0) {  
Log.d(“DataBaseHelper”, “migration is successful”);  
} else {  
// Handle migration failure  
throw new SQLiteException(“Cipher migration failed”);  
}  
} else {  
// Handle no result or cursor error  
throw new SQLiteException(“No result from PRAGMA cipher\_migrate”);  
}  
} catch (Exception e) {  
throw new SQLiteException(“Error executing PRAGMA cipher\_migrate”, e);  
}  
}  
});  
}  
});

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [June 26, 2024, 5:30pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/18 "2024-06-26T17:30:17Z")

</div>

Any suggestion please

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [June 27, 2024, 1:16pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/19 "2024-06-27T13:16:58Z")

</div>

Hi @Anshuman_Biswal,

What happens when you pull an existing SQLCipher 3 database off the device onto your local machine and attempt to run the `PRAGMA cipher_migrate` command on your host computer when using SQLCipher 4?

---

<div class="post-metadata">

**Author:** ![Anshuman\_Biswal](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/anshuman_biswal/32/2083_2.png) [@Anshuman\_Biswal](https://discuss.zetetic.net/u/Anshuman_Biswal)\
**Post date:** [August 12, 2024, 1:14pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/20 "2024-08-12T13:14:33Z")

</div>

I am really sorry.  
I am not getting exactly what we need to do here.

---

<div class="post-metadata">

**Author:** ![developernotes](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/developernotes/32/1309_2.png) [@developernotes](https://discuss.zetetic.net/u/developernotes)\
**Post date:** [August 12, 2024, 4:41pm UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/21 "2024-08-12T16:41:42Z")

</div>

Hello @Anshuman_Biswal,

I am asking you to extract the SQLCipher 3 database from an Android device onto a host computer, then run the SQLCipher command line shell program (using version 4.\*), opening the database and running `PRAGMA cipher_migrate`. What is your result from doing this?

---

<div class="post-metadata">

**Author:** ![xuhongchang](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.zetetic.net/xuhongchang/32/2192_2.png) [@xuhongchang](https://discuss.zetetic.net/u/xuhongchang)\
**Post date:** [May 14, 2025, 7:54am UTC](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370/22 "2025-05-14T07:54:30Z")

</div>

how to use SQLCipher command line? I dont have environment.

[Next page](https://discuss.zetetic.net/t/issue-migrating-from-android-database-sqlcipher-3-5-9-to-sqlcipher-android-4-5-5/6370.md?page=2)
