nolanlawson/emoji-picker-element

DOMException: Failed to execute 'transaction' on 'IDBDatabase'

tobyzerner opened this issue · 5 comments

If you remove an existing <emoji-picker> element and append a new one in the same tick, this error is logged to the console:

Uncaught (in promise) DOMException: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.

I'm encountering this in the real world using Turbo – my <emoji-picker> element is inside an element marked with data-turbo-permanent, so it is effectively removed, cloned and re-added to the page on navigation, causing this error.

Doesn't seem to impact functionality as far as I can tell.

Minimal reproduction: https://jsbin.com/seyocoyeqa/edit?html,output

Interesting. I assume the workaround is to use the same <emoji-picker> element, or to wait a tick using Promise.resolve() or something?

Also yes, you're right, this doesn't affect functionality. It's just a logged error; emoji-picker-element recovers.

FWIW the error message in Firefox is:

DOMException: IDBDatabase.transaction: Can't start a transaction on a closed database

Hi, I have the same issue, using Turbo in Rails application for chat. picker is part of the form and is being refreshed when I submit the form. I would get the same message in console.

@pruzicka This is just a warning message and you may safely ignore it. Although it indicates that the picker element is probably not being removed from the DOM / unloaded before a query is being executed on it.

Do you have a minimal repro test case?

It has to do something how the Turbo handle things. When I put it on the page just once and mess with the rest of the page with Turbo frames life is good. But as soon as I put it to one of the Turbo frames, replace it, change it, update it with the rest of the HTML, I got the message. I've tried to delay the initialisation, without success

  connect() {
    setTimeout(() => {
      this.initializePicker()
    }, 1000) 
  }
scuml commented

I was able to solve for this by assigning the initialized Picker to a window global. This way the Picker isn't reinitialzed on turbo-frame refreshes.

    if (window.trixChatEmojiPicker) {
      this.picker = window.trixChatEmojiPicker
    } else {
      this.picker = new Picker({
        customEmoji: [
          {
            name: 'Meow Party',
            shortcodes: ['meowparty'],
            url: 'https://emojis.slackmojis.com/emojis/images/1643514596/5999/meow_party.gif',
            category: 'Cats',
          },
         ...
        ],
      });
      window.trixChatEmojiPicker = this.picker
    }