Uncaught InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running
Asked Answered
U

4

25

i must admit that i am very new to indexedDB

I wrote a simple code of indexedDB and it is as followed:

function go() {
   var req = window.indexedDB.open("Uploader", 1),
      db;
   req.onerror = function (e) {
      console.log("Error");
   };
   req.onsuccess = function (e) {
      db = e.target.result;
   };
   req.onupgradeneeded = function (e) {
      console.log(db);
      db = e.target.result;
      var os = db.createObjectStore("Files", { keyPath: "files" });
      os.createIndex("text", "text_file", { unique: false });
      var trans = db.transaction(["text"], "readwrite");
      var objectstore = trans.objectStore("text");
      var addreq = objectstore.add("Instructions.js");
      addreq.onsuccess = function (e) {
         console.log("Success!");
         console.dir(e);
      };
   };
}

the error it is giving me is Uncaught InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running.

It is saying that A version change Transaction is running but as far as i have studied, a version change transaction is made from IDBFactory.open method and i haven't used and i have specified that this transaction is readwrite and this transaction is in onupgradeneeded then why there is an error?

i must admit that i am very new to indexedDB

Uniformed answered 14/11, 2015 at 15:27 Comment(0)
H
21

The versionchange transaction also allows you to readwrite. You just need to access the transaction created for you within the onupgradeneeded function.

var req = indexeddb.open(...);
req.onupgradeneeded = function(event) {
  // note that event.target === req === this, use whatever you like
  var db = event.target.result;

  // createObjectScore implicitly uses the versionchange txn running 
  // here, without telling you, basically a convenience function
  var objectStore = db.createObjectStore(...);

  // the important part that i am describing in this answer, 
  // grab the handle of the versionchange txn 
  // that is already running and was created for you
  // note again that event.target === req, you could just do
  // req.transaction or this.transaction here.
  // note this is a property of the open request, not a method.
  // do NOT confuse this with the method transaction() that is 
  // used to create a new transaction.
  var txn = event.target.transaction;

  // txn.objectStore(...) works here because the earlier
  // createObjectStore call guarantees the store exists
  // within the implicit upgrade txn
  var addRequest = txn.objectStore(...).add('value');

  // if in previous line we did:
  // var objectStoreRetrievedFromTxn = txn.objectStore(...);
  // then that variable is equal to the same variable returned from 
  // db.createObjectStore earlier in this function. Both are simply handles 
  // (references, pointers, whatever you want to call it) to the store.

 // silly example here if you want to known when the implicit txn 
 // completes. not very useful since success event will fire 
 // shorter after versionchange txn completes and you might as well
 // just wait for success
 addRequest.onsuccess = function() {console.log('Success!');};
};

// called once upgrade txn completes (if it even needed to run), 
// and db is opened
req.onsuccess = function(event) {
  console.log('upgrade txn completed and db is now connected');
  // here, create whatever readwrite or readonly txns you want, note these 
  // txns are separate from and different than the versionchange txn from 
  // before, because that is a unique transaction only available within 
  // onupgradeneeded. however, both versionchange and readwrite are similar
  // in that both support calls to put or add
};

You are encountering the error because you are trying to start a second transaction while the version change transaction is still running.

Hoopes answered 14/11, 2015 at 15:51 Comment(3)
but how do i specify the span of transaction?Uniformed
and it is giving me an error Uncaught NotFoundError: Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found. on line ` transaction.objectStore('text')`Uniformed
Interesting that inside the onupgradeneeded callback, db.transaction does not work but event.target.transaction does.Indiscipline
L
17

You need to check for the completion of the version change transaction before attempting to load the object store:

request.onupgradeneeded =
    function(event) {
        db = event.target.result;
        var store = db.createObjectStore('Files', {keyPath:"files"});
        var transaction = event.target.transaction;

        transaction.oncomplete =
            function(event) {    
                // Now store is available to be populated
            }
    }
Largehearted answered 16/3, 2016 at 2:9 Comment(0)
C
2

in a version change you do not need to specify a scope for the transaction. This is always all the prenset object stores. transaction.objectStore('text') here you are trying to open an object store with the name of the index, this isn't going to work. You need to go to the objectstore first if you want to access the index.

Adding data needs to be done on the objectstore.

function go(){var req = window.indexedDB.open("Uploader", 1), db;
req.onerror=function(e){console.log('Error')};
req.onsuccess = function(e){db=e.target.result;};
req.onupgradeneeded = function(e){
    console.log(db);
    db=e.target.result;
    var trans=e.target.transaction;
    var os = db.createObjectStore('Files', {keyPath:"files"});
        os.createIndex('text', 'text_file', {unique:false})
    var objectstore=  trans.objectStore("Files");
    var addreq = objectstore.add('Instructions.js');
        addreq.onsuccess = function(e)  {console.log('Success!');console.dir(e)}
}}

Give this a try

Collogue answered 16/11, 2015 at 8:17 Comment(0)
H
1

Always use the official IndexedDB specification. MDN lies, there are a lot of inaccuracies, especially when it comes to types.

const request = indexedDB.open("library", 3);
request.onupgradeneeded = function(event) {
  const db = request.result;
  const transaction = request.transaction;
  if (event.oldVersion < 3) {
    const bookStore = transaction.objectStore("books");
    const yearIndex = bookStore.createIndex("by_year", "year");
  }
};
Humerus answered 29/4, 2022 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.