# Runtime errors caused by Chrome extensions

**URL:** <https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381>\
**Category:** Request Feedback\
**Created:** [September 26, 2019, 12:58am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381 "2019-09-26T00:58:33Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [September 26, 2019, 12:58am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/1 "2019-09-26T00:58:33Z")

</div>

Hi everyone! I want some feedback about a well-known problem.

# Context

Some Chrome extension breaks the Virtual DOM system and it causes infinite runtime errors. I recently found this is a very serious problem because Sentry notifies runtime errors every day (from the production app, of course).

There has been some discussion about this problem but not solved for a long time. [discourse1](https://discourse.elm-lang.org/t/javascript-exception-cannot-read-property-childnodes-of-undefined-with-extension-dark-reader/2748) [discourse2](https://discourse.elm-lang.org/t/fullscreen-elm-app-in-0-19-childnode-issue-reopened/3174) [discourse3](https://discourse.elm-lang.org/t/elm-app-not-compatible-with-chromevox-screen-reader/3682) [github](https://github.com/elm/html/issues/44)

# Help wanted to gather information

In the discussions above, @evancz requests more information before fixing it. [1](https://discourse.elm-lang.org/t/fullscreen-elm-app-in-0-19-childnode-issue-reopened/3174/17) [2](https://discourse.elm-lang.org/t/fullscreen-elm-app-in-0-19-childnode-issue-reopened/3174/20)

> Before suggesting fixes based on whatever, I think there is information to gather:
> 
> 1. Make a list of the browser extensions that are known to cause problems.
> 2. Figure out how they are they modifying the `<body>` exactly. Adding at top? Adding at bottom? Adding indiscriminately somewhere in the DOM?
> 3. Sort the list of extensions by how they work.
> 4. Figure out how many people use these extensions, so we can weigh the importance in practice. Maybe certain categories of problem only show up in weird ones, but one category is super common and reasonable to work around in virtual-dom.
> 
> From there, it will be much easier to find a fix that makes sense for the actual reality of the situation.
> 
> Can folks in this thread work on gathering this information and come back with the lessons?

I think the best answer would be done by this format. ( **Edit** : The latest version is [here](https://github.com/jinjor/elm-break-dom#known-extensions))

| Plugin (Users) | Where | When | Workaround |
| --- | --- | --- | --- |
| [Grammarly](https://chrome.google.com/webstore/detail/grammarly-for-chrome/kbfnbcaeplbcioakkpcpgfkobkghlhen) (10,000,000+) | **middle in `<body>`** | focus on `<textarea>` | [`data-gramm_editor="false"`](https://github.com/elm/html/issues/44#issuecomment-534665947) |
| [ChromeVox](https://chrome.google.com/webstore/detail/chromevox-classic-extensi/kgejglhpjiefppelpmljglcjbhoiplfn) (161,918) | **top in `<body>`** | load, focus on something | [patch to output](https://github.com/jinjor/elm-break-dom#patch-for-browserapplication) |
| [Viber](https://chrome.google.com/webstore/detail/viber/dafalpmmoljglecaoelijmbkhpdoobmm) (133,220) | **top, bottom in `<body>`** | load | [patch to output](https://github.com/jinjor/elm-break-dom#patch-for-browserapplication) |

(!) The workaround is not fully tested. Use at your own risk.

**Do you know any other popular extensions?** Let’s add them too! (It is not necessary to strictly follow this format. Describe as you like.)

# Tests

I also created a project to test the problematic cases.

- repo: [jinjor/elm-break-dom](https://github.com/jinjor/elm-break-dom)
- site: [elm-break-dom.netlify.com](https://elm-break-dom.netlify.com/)

This test covers various patterns of breaking DOM.

- How to break? (insert, remove, etc.)
- How to initialize the app? (`Browser.application` or `Browser.element`)
- Where in the Virtual DOM is dangerous to update? (child, next element, attribute, etc.)

After this problem is fixed, all the test cases should be green. Also, you can try some of the tests online. Turn on and off your extensions to see how results change.

Any feedback about this project will also be welcome.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [September 26, 2019, 9:28am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/2 "2019-09-26T09:28:01Z")

</div>

Great initiative, thank you very much ❤

Maybe you could add a `<style>` node test inside the test page, because [Dark Reader](https://github.com/darkreader/darkreader) extension (1 763 020 users) for example will add its own `style` node just after an existing one if it is found in the DOM tree, leading to [runtime exceptions](https://github.com/darkreader/darkreader/issues/623).  
A [known workaround](https://github.com/mdgriffith/elm-ui/commit/02e9919a47d50a71fbc92338a8a38def853ffa0f) is to wrap `style` nodes into their own `div`.

Google translate (Chrome builtin extension, \> 10 000 000 users, most outside US) is also known to break some VDOM sites because it adds some `<font>` elements.  
For example the `update` button of your test page:

```auto
<button>update</button>

```

is replaced by

```auto
<button><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">mise à jour</font></font></button>

```

when translating in french.

I have not yet be able to reproduce the runtime error with your test page though, but it should not be hard with a few modifications. I know however that it can be disabled with `<meta name="google" content="notranslate">` in the `<head>`.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [September 26, 2019, 10:11am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/3 "2019-09-26T10:11:42Z")

</div>

Nice! I’ll add this information soon 😉

**Edit** : Done. The latest version is [here](https://github.com/jinjor/elm-break-dom#known-extensions).

---

<div class="post-metadata">

**Author:** ![berend](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/berend/32/2250_2.png) [@berend](https://discourse.elm-lang.org/u/berend)\
**Post date:** [September 26, 2019, 7:44pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/4 "2019-09-26T19:44:34Z")

</div>

Should the table not have a suggestion for Elm too? I.e. not taking over the body element fixes 99% of the extensions.

Well, I made that number up, but that surely goes a long way. So if we add that, we can get some idea of easy fixes.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [September 26, 2019, 8:54pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/5 "2019-09-26T20:54:40Z")

</div>

From my experience in this community, Evan tends to want a lot of information rather than suggestions. I guess he already has all the possible solutions and their trade-offs in his head. So let’s concentrate on gathering facts here.

---

<div class="post-metadata">

**Author:** ![berend](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/berend/32/2250_2.png) [@berend](https://discourse.elm-lang.org/u/berend)\
**Post date:** [September 26, 2019, 9:11pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/6 "2019-09-26T21:11:20Z")

</div>

I’m referring in particular to what Evan wrote:

> but one category is super common and reasonable to work around in virtual-dom.

So that’s why I’m suggesting to add something like a root cause, or fix. For example for your ChromeVox you describe a work-around, but it’s not clear why that work-around is needed or why it works.

So what about adding a column that describes to root cause, i.e. what does Elm do/not do that causes this problem? So for ChromeVox I would add: “taking over ”. This way we explicitly mention the category, something Evan asked for.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [September 26, 2019, 9:49pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/7 "2019-09-26T21:49:19Z")

</div>

I’m not sure I fully get what you mean, but if the “root cause” mean something like “this variable in this line is potentially `undefined`, so…”, it’s relatively easy to find (I believe). It should be clearer once someone starts debugging hard.

> For example for your ChromeVox you describe a work-around, but it’s not clear why that work-around is needed or why it works.

It avoids conflicting Elm and Chrome extension by separating the areas they control. Elm will treat a dummy element as the `<body>` element.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [September 27, 2019, 7:28am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/8 "2019-09-27T07:28:51Z")

</div>

> [@berend](#):
>
> So that’s why I’m suggesting to add something like a root cause, or fix.

I believe that the root cause is always the same, messing-up with elements controlled by the virtual DOM, usually adding children elements, leading to invalid modifications during an update after diffing. That’s why the most important factor is where is the DOM modification done:

- in the `body` itself or in another node?
- at the begining of the node, in the middle or at the end?

and this information is in [the table](https://github.com/jinjor/elm-break-dom#known-extensions).

Maybe we could add the kind of modification done, but I suspect that most of the time when it breaks elm, it is due to some added nodes (are there some agressive extensions that remove nodes?).

The potential most interesting fix(es) would have to be evaluated once we have enough data.

> [@berend](#):
>
> I.e. not taking over the body element fixes 99% of the extensions.

AFAICT this is exactly what the “patch to output” does, it moves elm to a `div` inside the `body` instead of letting it taking the whole `body` (for an application), so when it is in the table, it means that not replacing the body is a work-around.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [September 27, 2019, 11:48am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/9 "2019-09-27T11:48:54Z")

</div>

@jinjor thinking more about it:

- Maybe the table could show explicitly if the modification is in the `body` node itself or in a child node (or both)?
- Maybe ways to disable an extension should be separated from workarounds that allow the extension to work (different column)?

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [September 27, 2019, 4:39pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/10 "2019-09-27T16:39:40Z")

</div>

@dmy That may be good, but could be a bit complex for the first read? Anyway worth trying.

---

<div class="post-metadata">

**Author:** ![nk123](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nk123/32/2562_2.png) [@nk123](https://discourse.elm-lang.org/u/nk123)\
**Post date:** [October 1, 2019, 5:52pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/11 "2019-10-01T17:52:12Z")

</div>

Thank you for bringing this up once again. This is the number one problem in Elm! I mean how can I convince my team to invest in Elm if many popular extensions **will** break the app? Sooner or later. My arguments about easy refactoring and zero runtime errors will make me look silly in this context. This is the show stopper for the whole language.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [October 1, 2019, 9:36pm UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/12 "2019-10-01T21:36:46Z")

</div>

I agree! It’s a shame that only Elm has this problem in many JS frameworks like React and Vue.

---

<div class="post-metadata">

**Author:** ![albertdahlin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/albertdahlin/32/868_2.png) [@albertdahlin](https://discourse.elm-lang.org/u/albertdahlin)\
**Post date:** [October 2, 2019, 6:50am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/13 "2019-10-02T06:50:37Z")

</div>

When we upgraded our SPA sites to 0.19 and `Browser.application` we saw an increase of virtual dom related run time errors in our log tool (New Relic).  
This happened in all browsers, not only Chrome.  
This was due to people (not us) using Google Tag Manager to add 3rd party scripts (chats, marketing, re-targeting etc) to the `<body>` tag. This is a very common practice in e-commerce at least (which is what we do) and not something we have control over.

We rolled back to using `Browser.element` and ports+js for navigation and history and that made the errors go away.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [October 3, 2019, 12:46am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/14 "2019-10-03T00:46:31Z")

</div>

Yes. The cases of `Browser.application` have been discussed a lot, but I didn’t know the use of analytics tools can be uncontrollable. It’s good to know for me.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [October 4, 2019, 12:14am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/15 "2019-10-04T00:14:27Z")

</div>

# Status Update

I finally found potential way to fix this problem. [This patch](https://github.com/jinjor/elm-break-dom/blob/master/patch/VirtualDom.patch) should make elm/virtual-dom work safely with extensions (still WIP though). It works as follows:

1. Mark the DOM node as `created_by_elm`
2. If unknown nodes have been inserted, skip them.
3. If existing nodes have been removed, re-create them by old vdom.
4. If existing nodes have been replaced with unknown nodes, re-create them by old vdom.

See more details [here](https://github.com/jinjor/elm-break-dom/tree/master/patch). Also, you can [try it online](https://elm-break-dom.netlify.com/patched.html).

Since the elm/virtual-dom is the core of all Elm apps, enough tests should be done. Now I’m writing more tests ([example output](https://travis-ci.org/jinjor/elm-break-dom/builds/593298902#L324)), but it’s still not enough.

If you find any downside of this fix, please reply in this thread.  
(More information about extensions is still welcome too!)

---

<div class="post-metadata">

**Author:** ![albertdahlin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/albertdahlin/32/868_2.png) [@albertdahlin](https://discourse.elm-lang.org/u/albertdahlin)\
**Post date:** [October 4, 2019, 7:22am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/16 "2019-10-04T07:22:12Z")

</div>

Wouldn’t adding a mount node argument to `Browser.application`'s init function on the javascript side solve this?  
Like `Browser.element` has?  
It could even be optional so that existing apps don’t break. If `node:` is not set the `Elm.Main.init` it just uses `<body>` like today.

For our sites, switching to `Browser.element` did solve it.

```auto
<body>
  <div id="elm"></div>
  <script>
  var app = Elm.Main.init({
    node: document.getElementById('elm') // optional, uses body if not set
  });
  </script>
</body>

```

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [October 4, 2019, 8:09am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/17 "2019-10-04T08:09:12Z")

</div>

> Wouldn’t adding a mount node argument to `Browser.application` 's init function on the javascript side solve this?

The limitation that `Browser.application` always mount on `<body>` is [by design](https://github.com/elm/browser/blob/1.0.0/notes/navigation-in-elements.md). So we cannot expect it to be “fixed”.

Also, some extensions insert elements in the middle of the contents, not only at the start or end of `<body>`.

---

<div class="post-metadata">

**Author:** ![pdamoc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/pdamoc/32/36_2.png) [@pdamoc](https://discourse.elm-lang.org/u/pdamoc)\
**Post date:** [October 4, 2019, 9:37am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/18 "2019-10-04T09:37:27Z")

</div>

It might be useful to also have some benchmarks attached to this patch to show what would be the performance implications of this patch.

---

<div class="post-metadata">

**Author:** ![jinjor](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jinjor/32/386_2.png) [@jinjor](https://discourse.elm-lang.org/u/jinjor)\
**Post date:** [October 4, 2019, 10:04am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/19 "2019-10-04T10:04:03Z")

</div>

Thanks for the suggestion 👍

I _think_ this fix causes a big loss because it behaves (almost) as usual if there is no interruption. If there is, it re-creates DOM once but not more than once unless the extension continuously interrupts.  
Anyway, it is worth trying. There might be a mistake.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [October 14, 2019, 10:04am UTC](https://discourse.elm-lang.org/t/runtime-errors-caused-by-chrome-extensions/4381/20 "2019-10-14T10:04:04Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
