IndexedDB InvalidStateError: DOM IDBDatabase Exception 11

4,833 views
Skip to first unread message

Mathieu D

unread,
Aug 4, 2012, 5:57:00 AM8/4/12
to chromiu...@chromium.org
Sometimes an error occur when I want to create a transaction: InvalidStateError: DOM IDBDatabase Exception 11

A code sample would simply be:
var trans = db.transaction("myTest", "readwrite");

All I have to do is restart the browser and the application would execute fine again.
But still it is quite annoying for my users to see these pop-ups that an error occured and that they should restart their browser every time that happens ...

Chrome version is 21.0.1180.60 m


Joshua Bell

unread,
Aug 6, 2012, 1:23:24 PM8/6/12
to Mathieu D, chromiu...@chromium.org
My crystal ball tells me that you're making this call while a version change transaction is active. This is a spec requirement that we made sure Chrome aligned with in M21.

Your code might look something like this:

if (db.version !== '1') {
  req = db.setVersion('1');
  req.onsuccess = function () {
    db.createObjectStore(...);
    doStuff();
  };
} else {
  doStuff();
}

function doStuff() {
  db.transaction( ... ); // exception here
}

The spec [1] for IDBDatabase.transaction() says:

If this method is called on IDBDatabase object for which a "versionchange" transaction is still running, a InvalidStateError exception must be thrown.
  
You would need to change the above code to be as follows to ensure that the call to transaction() occurs after the version change transaction completes:

if (db.version !== '1') {
  req = db.setVersion('1');
  req.onsuccess = function () {
    db.createObjectStore(...);
    var trans = req.result;
    trans.oncomplete = doStuff;
  };
} else {
  doStuff();
}

function doStuff() {
  db.transaction( ... );
}

If my crystal ball is on the fritz, please provide more details about the code surrounding the transaction() call.

Mathieu D

unread,
Aug 6, 2012, 4:14:45 PM8/6/12
to chromiu...@chromium.org
Thank you Joshua, probably that was the issue.

Later I expect Chrome to implement callback onupgradeneeded when opening the DB (as Firefox does already) :

request.onupgradeneeded = function(e) {
[...]
myDB.setVersion(db);
}
request.onsuccess = function(e) {
[...]
doStuff(); 

I think this makes thing more clear. I don't need to add the code you mentionned like below in this case, right ?
var trans = req.result;
trans.oncomplete = doStuff;

Joshua Bell

unread,
Aug 6, 2012, 4:48:41 PM8/6/12
to Mathieu D, chromiu...@chromium.org
On Mon, Aug 6, 2012 at 2:14 PM, Mathieu D <mett...@gmail.com> wrote:
Thank you Joshua, probably that was the issue.

Later I expect Chrome to implement callback onupgradeneeded when opening the DB (as Firefox does already) :

request.onupgradeneeded = function(e) {
[...]
myDB.setVersion(db);
}
request.onsuccess = function(e) {
[...]
doStuff(); 

I think this makes thing more clear. I don't need to add the code you mentionned like below in this case, right ?
var trans = req.result;
trans.oncomplete = doStuff;

Yes; our implementation of the upgradeneeded event is in progress, we'll announce here when it's ready to play with in Canary builds.
 
On Saturday, August 4, 2012 12:57:00 PM UTC+3, Mathieu D wrote:
Sometimes an error occur when I want to create a transaction: InvalidStateError: DOM IDBDatabase Exception 11

A code sample would simply be:
var trans = db.transaction("myTest", "readwrite");

All I have to do is restart the browser and the application would execute fine again.
But still it is quite annoying for my users to see these pop-ups that an error occured and that they should restart their browser every time that happens ...

Chrome version is 21.0.1180.60 m


--
You received this message because you are subscribed to the Google Groups "Chromium HTML5" group.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msg/chromium-html5/-/_AxhJRxEJAIJ.

To post to this group, send email to chromiu...@chromium.org.
To unsubscribe from this group, send email to chromium-html...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-html5/?hl=en.

Joshua Bell

unread,
Aug 6, 2012, 4:50:05 PM8/6/12
to Mathieu D, chromiu...@chromium.org
On Mon, Aug 6, 2012 at 2:48 PM, Joshua Bell <jsb...@chromium.org> wrote:


On Mon, Aug 6, 2012 at 2:14 PM, Mathieu D <mett...@gmail.com> wrote:
Thank you Joshua, probably that was the issue.

Later I expect Chrome to implement callback onupgradeneeded when opening the DB (as Firefox does already) :

request.onupgradeneeded = function(e) {
[...]
myDB.setVersion(db);
}

Just to be clear: you don't need to call setVersion() in the upgradeneeded event handler; when you call db.open(name, version) it starts a version change transaction for you if necessary before it calls the upgradeneeded handler.

Daniel Gerson

unread,
Oct 10, 2012, 9:12:27 PM10/10/12
to chromiu...@chromium.org, Mathieu D


On Monday, August 6, 2012 10:50:05 PM UTC+2, Joshua Bell wrote:


On Mon, Aug 6, 2012 at 2:48 PM, Joshua Bell <jsb...@chromium.org> wrote:


On Mon, Aug 6, 2012 at 2:14 PM, Mathieu D <mett...@gmail.com> wrote:
Thank you Joshua, probably that was the issue.

Later I expect Chrome to implement callback onupgradeneeded when opening the DB (as Firefox does already) :

request.onupgradeneeded = function(e) {
[...]
myDB.setVersion(db);
}

Just to be clear: you don't need to call setVersion() in the upgradeneeded event handler; when you call db.open(name, version) it starts a version change transaction for you if necessary before it calls the upgradeneeded handler.

 Hi, I'm also having the error 11 issue. However mine seems to be different, here's the relevant code:
 
 function initDB() {
    var dbRequest = window.indexedDB.open(DB_NAME, DB_VERSION);
    dbRequest.onerror = function () { 
    alternativeStart();
    };
    dbRequest.onsuccess = dbSuccess;
    dbRequest.onupgradeneeded = verChangeSuccess;
   
}
function dbSuccess(evt)
{
db = evt.target.result;
 if (db.setVersion) {
        if (db.version != DB_VERSION) {
        dbOldVersion = parseInt(db.version) ;
            var verRequest = db.setVersion(DB_VERSION);            
            verRequest.onsuccess = verChangeSuccess;
            verRequest.onerror = function () { console.log("Error creating version change transaction"); 
            alternativeStart();};
        }
        else if (db.version == DB_VERSION) {
        dbActive = true;
        start();
        }
    }
    else {
    dbActive=true;
    start();
}
}

For me the previous db.version equals the new DB_VERSION, so I presume no new version changed transaction
is created. It's quite unreal how much boilerblate code there is to get going.

The error messages are not very explanatory.
Is it possible to query the db to ask if there are any version changed transactions open? That would be good.
If there aren't any open, then this isn't the problem.. what else could it be?

These guys had a similar problem : https://github.com/daleharvey/pouchdb/issues/126
but luckily it magically disappeared for them when they cleared out the db. I have a objectstore clear 
function, but it didn't work for me. It's a pity the API doesn't come with a reset database (would be great for testing).

I'm at quite a loss how to proceed. TIA.

Dan

David Grogan

unread,
Oct 11, 2012, 2:22:25 AM10/11/12
to Daniel Gerson, chromiu...@chromium.org
On Wed, Oct 10, 2012 at 6:12 PM, Daniel Gerson <daniel...@gmail.com> wrote:


On Monday, August 6, 2012 10:50:05 PM UTC+2, Joshua Bell wrote:


On Mon, Aug 6, 2012 at 2:48 PM, Joshua Bell <jsb...@chromium.org> wrote:


On Mon, Aug 6, 2012 at 2:14 PM, Mathieu D <mett...@gmail.com> wrote:
Thank you Joshua, probably that was the issue.

Later I expect Chrome to implement callback onupgradeneeded when opening the DB (as Firefox does already) :

request.onupgradeneeded = function(e) {
[...]
myDB.setVersion(db);
}

Just to be clear: you don't need to call setVersion() in the upgradeneeded event handler; when you call db.open(name, version) it starts a version change transaction for you if necessary before it calls the upgradeneeded handler.

 Hi, I'm also having the error 11 issue. However mine seems to be different, here's the relevant code:

What line is generating the exception?
 
 
 function initDB() {
    var dbRequest = window.indexedDB.open(DB_NAME, DB_VERSION);
    dbRequest.onerror = function () { 
    alternativeStart();
    };
    dbRequest.onsuccess = dbSuccess;
    dbRequest.onupgradeneeded = verChangeSuccess;

add dbRequest.onblocked = something; to see if a blocked event is getting fired.

   
}
function dbSuccess(evt)
{
db = evt.target.result;
 if (db.setVersion) {
        if (db.version != DB_VERSION) {
        dbOldVersion = parseInt(db.version) ;
            var verRequest = db.setVersion(DB_VERSION);            
            verRequest.onsuccess = verChangeSuccess;
            verRequest.onerror = function () { console.log("Error creating version change transaction"); 
add verRequest.onblocked = something;
 
            alternativeStart();
 
};
        }
        else if (db.version == DB_VERSION) {
        dbActive = true;
        start();
        }
    }
    else {
    dbActive=true;
    start();
}
}

For me the previous db.version equals the new DB_VERSION, so I presume no new version changed transaction
is created.
 
It's quite unreal how much boilerblate code there is to get going.

Yeah, it is unfortunate.

The error messages are not very explanatory.
Is it possible to query the db to ask if there are any version changed transactions open? That would be good.
If there aren't any open, then this isn't the problem.. what else could it be?

These guys had a similar problem : https://github.com/daleharvey/pouchdb/issues/126
but luckily it magically disappeared for them when they cleared out the db. I have a objectstore clear 
function, but it didn't work for me. It's a pity the API doesn't come with a reset database (would be great for testing).

I'm at quite a loss how to proceed. TIA.

Dan

--
You received this message because you are subscribed to the Google Groups "Chromium HTML5" group.

Daniel Gerson

unread,
Oct 11, 2012, 10:36:55 AM10/11/12
to chromiu...@chromium.org, Daniel Gerson
In response to the question of which line it is happening on, it's happening somewhere in the Start() function. Unfortunately, there is quite a lot of async events happening (from ajax and other bits in the code, not just indexedDB) and given that this is all happening in a unit-test, I actually am not 100% sure of the offending line, except I know it happens after processing a cursor on one of the object stores. (The sinon mocking-framework unfortunately catches the error and doesn't bubble the stacktrace correctly.)

But, it is not happening in the code above, given that the DB versions are equal. So it doesn't make sense for Joshua Bell's description to apply to me. Even stranger, after adding and removing the Microsoft IndexedDB-debugger iframe from the test ( http://ie.microsoft.com/testdrive/HTML5/newyearslist/ ), the error has disappeared, without changing any other code. This is really scary stuff and I'm feeling very uncomfortable about thinking of moving it into production.

Can transactions remain open between page reloads?

Joshua Bell

unread,
Oct 11, 2012, 1:10:19 PM10/11/12
to Daniel Gerson, chromiu...@chromium.org, Mathieu D
On Wed, Oct 10, 2012 at 6:12 PM, Daniel Gerson <daniel...@gmail.com> wrote:
 It's quite unreal how much boilerblate code there is to get going.

Once you can rely on upgradeneeded being present the code ends up being much simpler. I'd recommend trying one of the shims linked to in previous threads which hide the complexity (and once everyone is on 24 you can just drop the shim)

The error messages are not very explanatory.

The exception should include the line number indicating where it was thrown, if you can get it to the debug console. I realize you're fighting against the unit test framework, though. One thing you can do is just start dropping in the equivalent of "fail_the_test_now(); return;" into your code and binary-search until you find where it's happening.
 
Is it possible to query the db to ask if there are any version changed transactions open? That would be good.

No, but this could be implemented yourself by logging (or setting state) at the start (setversion success event, upgradeneeded event, and transaction complete/abort events)
 
If there aren't any open, then this isn't the problem.. what else could it be?

Checking the code there are 30 places that emit InvalidState errors; these should match the spec.  Quickly summarizing: 
  • Calling a method on a cursor that hasn't "got value"
  • Creating/deleting an store/index outside a versionchange transaction
  • Creating a transaction on a database connection with a running versionchange transaction
  • Creating a transaction on a closed/closing database connection
  • Calling a method on a deleted store/index
  • Accessing error/result on a request that isn't readyState === "done"
  • Calling objectStore or abort on a transaction that's finished
These guys had a similar problem : https://github.com/daleharvey/pouchdb/issues/126
but luckily it magically disappeared for them when they cleared out the db. I have a objectstore clear 
function, but it didn't work for me. It's a pity the API doesn't come with a reset database (would be great for testing).

How would that differ from deleteDatabase() ?

Daniel Gerson

unread,
Oct 11, 2012, 2:38:18 PM10/11/12
to chromiu...@chromium.org, Daniel Gerson
Thanx Joshua and David for your replies.
It's very good to know that there is such good support in Chromium for these kind of questions. I appreciate you summarizing the list of invalid state occurrences. I'm sure it will be useful for anyone else searching the web in the future.

Doh, somehow I completely missed deleteDatabase!!!
Possibly because the answers in this question are misleading. http://stackoverflow.com/questions/9384128/how-to-delete-indexeddb-in-chrome

Don't you know Google is the port of call for an API, and not the official API?!?   :-P

...since the error has disappeared, I can't investigate more for now. I'm going to put an arb query when the code first runs just to ensure the db is working, and send the code down a non-db path if that check fails. Thanks for the advice about the shim, but since onUpgradeNeeded is coming out soon, I'm going to wait it out... (I'm still not convinced that my problems originate from setVersion)...

Thanx
Dan
Reply all
Reply to author
Forward
0 new messages