Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null #2086

Closed
burningTyger opened this issue Feb 15, 2019 · 39 comments
Closed
Labels

Comments

@burningTyger
Copy link
Contributor

I couldn't reproduce the error in the repl and I also can't post the data since it is confidential.
I'll try to post as much information as possible though.

This is the component:

  {#each schueler as s (s.ID)}
    {#each s.abschnitte.filter(aktJahr) as a (a.ID)}
        <Voffset/>{a.Jahr}
    {/each}
  {/each}

<script>
  import Voffset from './partials/Voffset.html'
  // the file looks like this
  // ./partials/Voffset.html
  // <div></div>

  export let jahr, schueler
  // schueler looks like this just way more complex and about 1MB in size
  // schueler = [{abschnitte: [{Jahr: 2017},{Jahr: 2018}]}, {abschnitte: [{Jahr: 2017},{Jahr: 2018}]}]
  $: aktJahr = a => a.Jahr === jahr
</script>
svelte = new Component({ target: document.querySelector('svelte'), props })

this works just fine.

later on when I change some props I do it like this:

svelte.$set({ jahr: abschnitt.jahr, abschnitt: abschnitt.abschnitt })

sometimes it works, sometimes not. It renders the component but then fails and I can't change the data again.

This is the error message:

internal.mjs:111 Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null
    at detachNode (VM110 bundle.js:113)
    at Object.destroy [as d] (VM110 bundle.js:1555)
    at destroyBlock (VM110 bundle.js:1006)
    at on_outro (VM110 bundle.js:1012)
    at run (VM110 bundle.js:23)
    at Array.forEach (<anonymous>)
    at run_all (VM110 bundle.js:31)
    at check_outros (VM110 bundle.js:535)
    at Object.update [as p] (VM110 bundle.js:1675)
    at update (VM110 bundle.js:937)

this seems to only happen with two nested loops and the imported component.

@burningTyger
Copy link
Contributor Author

A very simple and well working workaround (not even a speed penalty so far) seems to be a destroy() and recreation of the component. Should have tried that earlier than setting the data.

@thgh
Copy link
Contributor

thgh commented Feb 19, 2019

I have also encountered this, but cannot reproduce at the moment. It went usually like this:

  1. Visit /items
  2. Click link to /items/[id]/specific (happens to be a sapper app)
  3. Click link to /items
    => empty page and console shows: TypeError: Cannot read property 'removeChild' of null

@ciri
Copy link

ciri commented May 9, 2019

Same issue is happening to me while using Sapper when navigating randomly. Very hard to reproduce but it happens often enough for it to be a problem.

I've also seen it happen when some library replaced DOM objects leaving it in a state that svelte is confused about. My temp fix is to change line 130 of node_modules/svelte/internal.mjs to:

function detach(node) {
	if(node.parentNode) {
		node.parentNode.removeChild(node);
	}
}

UPDATE: in the latest version this is located at line 181.

@tohlenforst
Copy link

I was having the same exact issue while working with <svelte:component> used alongside <svelte:window on:hashchange>. It was working fine until the components I was loading dynamically were using katex. The fix mentioned by @ciri worked. Currently I'm using patch-package on npm to apply the patch until it is fixed.

@csdswarm
Copy link

csdswarm commented May 31, 2019

this is happening to me when I am using a hashchange event as well (not sure if that's the reason or not, but since someone else mentioned it)

I am using an array that has values, then on a hash change, a filter is applied. Whenever that filter comes up with an empty array as the result, when there was something in the array to begin with, then this error seems to happen for me.

assume item => false is a filter function that ends up removing all items from the array.

$: filteredItems = items.filter(item => false)

I'm seeing the issue in the same place ciri did.
#2086 (comment)

@VelikiiNehochuha
Copy link

VelikiiNehochuha commented Jun 11, 2019

// first load — remove SSR'd <head> contents
const start = document.querySelector('#sapper-head-start');
const end = document.querySelector('#sapper-head-end');

if (start && end) {
  while (start.nextSibling !== end) detach(start.nextSibling);
  detach(start);
  detach(end);
}

node.nextSibling -

A Node object, representing the next sibling of the node, or null if there is no next sibling

I get error on first load, the detach calls from code above.

Bug when I add description into head.

<svelte:head>
  <title>test</title>
  <description>test</description>
</svelte:head>

My bad, I've added description instead meta tag. Should be

<svelte:head>
  <title>test</title>
  <meta name="description" content="Free Web tutorials">
</svelte:head>

@babycourageous
Copy link

In case it helps -
I had this error as well - I just updated svelte to @3.6.1 and rollup and the accompanying rollup packages (rollup@1.16.2, rollup-plugin-commonjs@10.0.1, rollup-plugin-node-resolve@5.1.
0, rollup-plugin-terser@5.0.0) to their latest and it seems to have gone away.

@ematipico
Copy link
Contributor

ematipico commented Jun 30, 2019

I started to have this issue (randomly) once I upgraded to version 3.6.x

@Rich-Harris
Copy link
Member

If anyone can provide a repro, that'd be helpful

@RobbieTheWagner
Copy link

RobbieTheWagner commented Jul 1, 2019

This is happening to me when I try to use {#each} in <svelte:head>, in Sapper.

@btakita
Copy link
Contributor

btakita commented Jul 2, 2019

This occurs using sapper when I have a route define a <meta> tag inside of <svelte:head>, then navigate to another route using goto. Having <title>inside of <svelte:head> seems to work.

<script>
	let description = 'foobar'
</script>

<svelte:head>
	<meta name="description" content="{description}"/>
</svelte:head>

This is a hunch, but would it simplify things if src/template.html were src/_template.svelte (a Svelte component) instead?

@btakita
Copy link
Contributor

btakita commented Jul 2, 2019

Since this issue seems to pop up periodically, it would be useful to turn this into a warning. It may not be elegant, but it prevents surprise blank screens due to a navigation error.

function detach(node) {
    if (node && node.parentNode) node.parentNode.removeChild(node);
    else if (node) console.warn('node ' + node + ' is detached. Please submit a bug report.');
    else console.warn('node is falsy. Please submit a bug report.');
}

@alexdilley
Copy link

Seeing this too since 3.6.x (tested good in 3.5.4, bad in 3.6.1). Same as @btakita for me; if I take meta tag definitions out of <svelte:head> then no error. Therefore if you take svelte/realworld, upgrade and add <meta name="description"> to root route and then log-in then I suspect the error will occur.

@burningTyger
Copy link
Contributor Author

I forgot to mention in the original issue way back that I have a lot of data. Like 1 to 3 MB that is being passed around via export let foo.

@btakita
Copy link
Contributor

btakita commented Jul 2, 2019

I pushed a hotfix, based on v3.6.3 proposed by #2086 (comment)

In package.json, under devDependencies, use:

"svelte": "btakita/svelte#svelte-gh-2086-hotfix"

I pushed the build files & tested it in my environment so this should work as is.

@RobbieTheWagner
Copy link

@btakita your fix works great for me! No errors and the meta updates in the head of each route 😃. Is this fix going to be included in an actual release?

@burningTyger
Copy link
Contributor Author

burningTyger commented Jul 5, 2019

These lines cause the error again when the button is clicked twice: https://gist.github.com/burningTyger/d21f7907820e46ad23bce0b845fb67b9#file-asz-svelte-L64-L79

I couldn't reproduce it in the REPL since this component needs a lot of data and I can't share it.
compiled it looks like this: https://gist.github.com/burningTyger/d21f7907820e46ad23bce0b845fb67b9#file-bundle-js

The error might be of interest too:

VM128 bundle.js:135 Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null
    at detach (VM121 bundle.js:135)
    at Object.destroy [as d] (VM121 bundle.js:2367)
    at outros.callbacks.push (VM121 bundle.js:632)
    at run (VM121 bundle.js:20)
    at Array.forEach (<anonymous>)
    at run_all (VM121 bundle.js:26)
    at check_outros (VM121 bundle.js:615)
    at Object.update [as p] (VM121 bundle.js:3760)
    at update_keyed_each (VM121 bundle.js:955)
    at Object.update [as p] (VM121 bundle.js:3825)

btakita added a commit to btakita/svelte that referenced this issue Jul 7, 2019
@btakita
Copy link
Contributor

btakita commented Jul 7, 2019

@rwwagner90 I updated another hotfix branch to account for v2.6.5. It's at btakita/svelte#gh-2086-hotfix

There have been some attempts to fix some of the root causes of calling detach when the DOM element is already detached as seen in #3172. However, it's not yet merged due to an issue.

I created a pull request to have the if (node.parentNode) conditional added to detach. It was not applied due to the desire to find the root cause of the <meta> tag manifestation of this issue.

However, IMO, having the conditional in the detach function is necessary, because there are other manifestations of this error. For example, if the DOM element in a component is removed from software outside of svelte, detach will have the same error.

I'm not sure where the core team currently stands on this issue & fix(es). IMO, the conditional needs to be added to detach to fix all manifestations of this error. Ontologically, detach, as an api, should be declarative (ensure the node is detached) instead of imperative (detach the node), allowing it to be called multiple times by performing a noop if the node is already detached. This way, it won't matter if the node is removed from the DOM from outside of svelte.

I'll keep btakita/svelte#gh-2086-hotfix up to date with the latest release in the meantime.

@tohlenforst
Copy link

I'm still having this issue. Unfortunately, I could not find a way to replicate the issue on the REPL, so here it is in a repo: https://gitlab.com/tohlenforst/issue2086

git clone https://gitlab.com/tohlenforst/issue2086
npm i
npm run dev

Then just click on a link and then try to click a different link.

@sinistra
Copy link

Can reproduce this error on demand.
Using:
"rollup": "^1.21.2",
"rollup-plugin-commonjs": "^10.0.0",
"rollup-plugin-livereload": "^1.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-postcss": "^2.0.3",
"rollup-plugin-scss": "^1.0.2",
"rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^4.0.4",
"svelte": "^3.12.0",
"svelte-material-ui": "^1.0.0-beta.14",
"svelte-routing": "^1.4.0"

svelte-material-ui has a component call 'snackbar'.
This component is modal and has child nodes.
Using this component and then existing the current page (moving to another) provokes this error.

Updating line 145 of 'node_modules/svelte/internal/index.mjs' to
function detach(node) {
if(node.parentNode) {
node.parentNode.removeChild(node);
}
}
steps around the error.

@MintyMods
Copy link

I have also been struggling with this while using a svelte-material-ui List component containing dynamically loaded FontAwesome SVG icons where I could load a list of the icons fine, then load another couple before the following exception is thrown :-

Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null
    at detach (index.mjs:142)
    at Object.d (Span.svelte:2)
    at destroy_component (index.mjs:1220)
    at Object.d (ClassAdder.svelte:2)
    at destroy_component (index.mjs:1220)
    at Object.d (SensorList.svelte:61)
    at Object.d (Item.svelte:43)
    at Object.d (Item.svelte:18)
    at destroy_component (index.mjs:1220)
    at Object.d (SensorList.svelte:61)

Applying the previous fix from @sinistra allows me to continue (Thanks for that sinistra much appreciated)

For reference my dependencies are as follows:-

  "devDependencies": {
    "@fortawesome/fontawesome-pro": "^5.10.1",
    "cross-env": "^5.2.1",
    "css-loader": "^2.1.1",
    "mini-css-extract-plugin": "^0.6.0",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.3.1",
    "serve": "^11.1.0",
    "style-loader": "^0.23.1",
    "svelte": "^3.9.1",
    "svelte-loader": "^2.13.3",
    "svelte-material-ui": "^1.0.0-beta.9",
    "svelte-spa-router": "^1.2.0",
    "webpack": "^4.39.3",
    "webpack-cli": "^3.3.7",
    "webpack-dev-server": "^3.8.0"
  },
  "dependencies": {
    "@simonwep/pickr": "^1.2.6",
    "@stomp/stompjs": "^5.4.2",
    "canvas-gauges": "^2.1.5",
    "chart.js": "^2.8.0",
    "date-fns": "^2.1.0",
    "highcharts": "^7.1.2",
    "masonry-layout": "^4.2.2",
    "packery": "^2.1.2",
    "pnotify": "^4.0.0",
    "sockjs": "^0.3.19"
  }

Not complaining, Svelte is AWESOME!!

@carcinocron
Copy link

Why is this closed? I still have to manually add this to make my app work:

function detach(node) {
	if(node.parentNode) {
		node.parentNode.removeChild(node);
	}
}

@MintyMods
Copy link

@InstanceOfMichael I can't comment on your specific use case but my issue is no longer reproducible against version 3.13.0-alpha.17 after confirming the patch is no longer in place e.g.

function detach(node) {
    node.parentNode.removeChild(node);
}

I am actually not sure if anything changed within Svelte or just reworking my code resolved the issue (I was previously not using a unique enough key within my {#each...})

I appreciate this probably doesn't help you but thought I would provide an update.

@jasdeepsingh
Copy link

jasdeepsingh commented Nov 18, 2019

I'm still facing this issue:

"devDependencies": {
    "@rollup/plugin-alias": "^2.2.0",
    "dotenv": "^8.2.0",
    "node-sass": "^4.13.0",
    "rollup": "^1.26.3",
    "rollup-plugin-commonjs": "^10.0.0",
    "rollup-plugin-livereload": "^1.0.0",
    "rollup-plugin-multi-entry": "^2.1.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-postcss": "^2.0.3",
    "rollup-plugin-replace": "^2.2.0",
    "rollup-plugin-svelte": "^5.0.3",
    "rollup-plugin-terser": "^5.1.2",
    "sirv-cli": "^0.4.4",
    "svelte": "^3.14.1",
    "svelte-preprocess": "^3.2.6"
  },
index.mjs:147 Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null
    at detach (index.mjs:147)
    at detach_dev (index.mjs:1430)
    at update (index.mjs:637)
    at flush (index.mjs:611)

One very specific block of code that's causing this issue is this very simple if statement in my code:

{#if $someStore}
    <i class="fas fa-angle-right" aria-hidden="true"></i>
{:else}
    <i class="fas fa-angle-down" aria-hidden="true"></i>
{/if}

Removing this piece of code fixes the issue for me, But I cannot figure out why this is happening, the error triggers whenever there's an update to the store or any other reactive value.

@rudolfs
Copy link

rudolfs commented Nov 26, 2019

I seem to have a very similar issue to @jasdeepsingh (I'm on svelte 3.0.0):

{#if $objectType === "blob"}
  <FileSource />
{:else}
  <FileList />
{/if}
Uncaught (in promise) TypeError: Cannot read property 'removeChild' of null
    at detach (index.mjs:146)
    at detach_dev (index.mjs:1372)
    at Object.destroy [as d] (FileList.svelte:116)
    at Object.destroy [as d] (FileList.svelte:92)

Weirdly this issue doesn't happen if I add some debug statements to the file with the if branch like so:

revision: {$revision}<br />
objectPath: {$objectPath}<br />
objectType: {$objectType}<br />

{#if $objectType === "blob"}
...

@rudolfs
Copy link

rudolfs commented Nov 26, 2019

The upgrade to Svelte 3.15.0 fixed it for me.

@kilianso
Copy link

function detach(node) {
	if(node.parentNode) {
		node.parentNode.removeChild(node);
	}
}

This answer is the only fix, that worked for me. I'm using Svelte 3.20.1

I'm using a third party library (sortable.js) where items are cloned into a dropzone. From there, they can be deleted again by a button (which removes the DOM node). Each item is a Item.svelte component. Dropzone.svelte is the wrapper.

As soon as i delete an item out of the dropzone and try to change the route, the parentNode.removeChild error appears in the console.

I also tried to add an additional wrapper within Item.svelte and just delete its content, rather than the node itself. This would work as well, but it causes side effects with the third party library and would require additional logic.

So, what is the point of not checking if there is a parentNode in any case in the internal/index.mjs file? Feels kinda unsafe to change a file in the node modules.

krwenholz added a commit to krwenholz/turning-point-tales that referenced this issue Mar 27, 2020
Should resolve some SEO issues. Also added meta tags.

Also required a new Svelte version. There were bugs with aforementiend
meta tags.

sveltejs/svelte#2086
@clineamb
Copy link

clineamb commented Apr 9, 2020

I am also having the above issue still, and I am trying to just use a dynamic component <svelte:component>

@curioustolearn
Copy link

curioustolearn commented Jun 16, 2020

Is there a fix for this? I believe I am using svelte 3.23.2 (based on the Changelog.md file).

The following works:

function filterAndRenderMath(topics) {
     filter(selectedTags);
     await tick();
     // renderMathInElement is defined by the KaTeX autorender, sourced in html file.
     //   if (typeof(renderMathInElement) !== "undefined") {
     //       renderMathInElement(document.body);
       // }
}

But if I uncomment the commented lines: it gives me the error mentioned above, if the selectedTags variable changes. Essentially, svelte is not playing well with KaTeX. Any workarounds I can use?

If possible, I would prefer not to change the lines in internal.mjs, as suggested above. @burningTyger mentioned something about destroying the component and rerendering. Can someone please point out how I can do that?

Would really appreciate your help. I am a svelte newbie.

@curioustolearn
Copy link

Just wanted to update with the things I tried:

I searched some more for how I could destroy the content that was giving trouble and re-render.
It appears that putting that part in a #if block and setting it to first to false and and then true could work. I tried that, but that did not help me.

Then, I tried the solution suggested by @ciri. The file he mentions does not exist in svelte 3.23.2. But I found that content in both svelte/internal/index.js and svelte/internal/index.mjs. By itself, the solution did not work.

Both of the above combined, however, do work.

@shedali
Copy link

shedali commented Jun 30, 2020

I've also seen it happen when some library replaced DOM objects leaving it in a state that svelte is confused about.

easily reproducible by embedding twitter or instagram embed widgets in sapper;

@torgebauer
Copy link

Still running in this issue. I use a lot of dynamic components svelte:component that are leading into huge changes in the DOM (typically enterprise web application with many different tabs). I think it is related to the usage of svelte transitions. Made all of them to local transitions, but still running into this issue.

function detach(node) { if(node.parentNode) { node.parentNode.removeChild(node); } }

The code above fixes the error, but then my DOM is not correct and some elements are still there. Sometimes this is a crazy UI behaviour when something from an other Tab is merged into the new one. Is there any other solution?

@cliedelt
Copy link

It fixed the error on my project too with:
function detach(node) { if(node.parentNode) { node.parentNode.removeChild(node); } }

I can not understand why it should effect the DOM negativ like @torgebauer wrote.

@sudomaxime
Copy link

I am still having this issue.

@jycouet
Copy link

jycouet commented Mar 1, 2021

@orgertot & @torgebauer , where did you put this line?
function detach(node) { if(node.parentNode) { node.parentNode.removeChild(node); } }

I don't find the root cause of my Cannot read property 'removeChild' of null, so I would like to check if it's null like you.
Any hint on how to find the root cause?

@tanhauhau
Copy link
Member

tanhauhau commented Mar 1, 2021

Please stop commenting on a closed issue.

It's not helpful commenting on a closed issue, and even though you may get the same error, it may due to different reasons.

So, please, if you need support on this, please comment your repro on this new issue i just created.

@jycouet @sudomaxime @torgebauer @orgertot @shedali @clineamb @kilianso

@sveltejs sveltejs locked as resolved and limited conversation to collaborators Mar 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.