Is there a way to rebuild Dexie keys?

I had a working app that uses Dexie. After updating to iOS 10.3, keyword search does not work. (This is actually an indexeddb issue, not Dexie per se, I'm sure.) I'm still in shock, but I was able to confirm that the data is there by doing db.table.each (function (p) {}, and fields, used in the keys are there and are correct. But if I do this db.table.get (primarykey, function (p) {} or db.table.where ("somekey"). equals (nonprimarykey) .first (function (p) {} p undefined.

I tried to do .db.table.each and then return each returned object to see if that would rebuild the keys, and it worked in Firefox but not in Safari or Chrome (still can't get the key).

I also tried to specify a newer version with the same key structure and empty update and it didn't do anything (but I only tried this in Chrome).

It's okay if the database is created AFTER installing 10.3, but I hope my clients don't have to drop their databases.

Is there a way to recover this without losing data?


source to share

2 answers

This seems to be an update bug in Safari and should really be posted to Let's assume it gets fixed there, as the Safari team is very responsive when it comes to critical bugs. Please register it!

As for a workaround, I would suggest recreating the database. Copy the database to the new database, delete it, then copy and delete the intermediate copy. I have not tested the code below, so you need to test it.

function check_and_fix_IOS_10_3_upgrade_issue () {
    return (somehowCheckIfWeNeedToDoThis) ?
        recreateDatabase() : Promise.resolve();

function recreateDatabase () {
    copyDatabase("dbName", "dbName_tmp").then(()=>{
        return Dexie.delete("dbName");
        return copyDatabase("dbName_tmp", "dbName");
        return Dexie.delete("dbName_tmp");

function copyDatabase(fromDbName, toDbName) {
    return new Dexie(fromDbName).open().then(db => {
        let schema = db.tables.reduce((schema, table) => {
            schema[] = [table.schema.primKey.src]
                .concat( => idx.src))
        }, {});

        let dbCopy = new Dexie(toDbName);

            // dbCopy is now successfully created with same version and schema as source db.
            // Now also copy the data
            return Promise.all(
                    table.toArray().then(rows => dbCopy.table(;


As far as "somehowCheckIfWeNeedToDoThis" is concerned, I cannot answer exactly how to do it. Maybe user agent sniff + cookie (set a persistent cookie when fixed so it doesn't get recreated over and over). Perhaps you can find a better solution.

Then, before opening your database (perhaps before starting your application), you need to do something like:

    .catch(err => {
        // Display error, to user




I faced the same problem using db.js library . All my app data is erased when I update.

Based on my tests, it looks like updating 10.2 → 10.3 clears any data in tables for which autoIncrement is set to false. The data saved in autoIncrement = true is still available after the update.

If so, this is a pretty serious mistake. Safari's autoIncrement feature had a lot of problems and made many of us switch to managing our own IDs.

I haven't tested this theory with vanilla JS yet. if anyone wants to do this, add your results to ticket



All Articles