nuxt: Failed to execute 'appendChild' on 'Node': This node type does not support this method.

Version

2.6

Reproduction link

http://demo.xibangtech.com/

Steps to reproduce

Source: https://github.com/xibang/xibang.tech

Localhost dev is ok, but when nuxt generate and deploy to server, it occurs error. Besides, all links cannot click then.

What is expected ?

generate and work.

What is actually happening?

Error: [nuxt] Error while mounting app: HierarchyRequestError: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
    at 624151740479ce035ad7.js:1

more

build - ssr - set to false, then localhost develop:

Nuxt.js: Loading app...

auto refresh and refresh … endless

<div align="right">This bug report is available on Nuxt community (#c9262)</div>

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 12
  • Comments: 106 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Here is how I fixed it:

yarn add gulp gulp-html-minifier

then create gulpfile.js

const { src, dest } = require('gulp')
const htmlmin = require('gulp-html-minifier')

function minify() {
  return src('./dist/**/*.html')
    .pipe(htmlmin({ removeComments: true, collapseWhitespace: true }))
    .pipe(dest('./dist'))
}

exports.default = minify

in package.json for generate script do this: nuxt generate && gulp

Thanks for this. I have tried everything, only your method works!

This can be done in nuxt.config.js, without gulp:

module.exports = {
  build: {
    html: {
      minify: {
        collapseWhitespace: true,  // as @dario30186 mentioned
        removeComments: true, // 👈 add this line
      },
    },
  },
};

Here is how I fixed it:

yarn add gulp gulp-html-minifier

then create gulpfile.js

const { src, dest } = require('gulp')
const htmlmin = require('gulp-html-minifier')

function minify() {
  return src('./dist/**/*.html')
    .pipe(htmlmin({ removeComments: true, collapseWhitespace: true }))
    .pipe(dest('./dist'))
}

exports.default = minify

in package.json for generate script do this: nuxt generate && gulp

Changing mode: 'universal' to mode: 'spa' fixed this for me, but this should be somehow mentioned in the docs, that using generate could lead to those problems.

I have same issue too

@itzaks In my case I have diagnosed the problem now, but don’t know how to fix it. I’ve narrowed it down to the Netlify Forms. The problem only happens on the branch I have them on. What happens is Netlify adds a hidden input , but the problem is: they are closing their input!:

<input type='hidden' name='form-name' value='contact-form' />

It’s not valid HTML!

In my case, Chrome tried to somehow guess what was happening and in its confusion it nested an input with a label inside that hidden input, but again its not valid HTML as input tags are void and should not have anything inside them! It’s so frustrating when everything is fine on your development machine, but something unexpected happens 😕

I’m also having the same issue, shows up from time to time when deploying on netlify with nuxt generate. Don’t really know what’s causing it… I’m trying to find out.

I have also run into same issues

Hi, I solved this issue with the following configuration in nuxt.config.js:

module.exports = { build: { html: { minify: { collapseWhitespace: true } },

This avoids to add gulp to project dependencies

it’s a bug and just fix it. why should i use tricks?

In my case the same error was occured when a computed property returning vuetify breakpoint has been used in v-if directive. So the solution was just to add a boolean data object, set it to true in onMounted hook and to use it as breakpoints mount indicator exactly like here: 3436# comment. There is also a solution based on mixins (just scroll down a bit).

@itzaks In my case I have diagnosed the problem now, but don’t know how to fix it. I’ve narrowed it down to the Netlify Forms. The problem only happens on the branch I have them on. What happens is Netlify adds a hidden input , but the problem is: they are closing their input!:

<input type='hidden' name='form-name' value='contact-form' />

It’s not valid HTML!

In my case, Chrome tried to somehow guess what was happening and in its confusion it nested an input with a label inside that hidden input, but again its not valid HTML as input tags are void and should not have anything inside them! It’s so frustrating when everything is fine on your development machine, but something unexpected happens 😕

Thanks for this tip. I manually added the generated input to my template so Netlify doesn’t have to and it works like a charm

@bengineer19 basically nuxt generates some weird tags on html, so I just post-process the html to get rid of it.

Hi all!

Just wanted to say that I’ve encountered this same issue.

I’ll describe how I found the error and how I solved it:

  1. Our website is statically deployed on an AWS bucket. The issue occurred only after using the generate command. If a user opened the website and got to be handled by Nuxt SPA fallback, every component worked just fine.
  2. However, since generate creates a folder named like the url and places an index.html file inside it, after a user clicked the browser refresh button on the page (for example) /en/home, AWS Cloudfront made a redirect to the address /en/home/, throwing the error.
  3. After a very long investigation, I luckily noticed that the button used to change the locale was not rendered on the /en/home/ page while it was correctly displayed on the /en/home.
  4. Opening its relative file inside the dist folder created by generate, I found out that the two buttons were not rendered by generate.
  5. Since I’ve read some of the comments here about people solving the issue by using a v-show instead, I tried to remove the component, rebuilt the website and the page worked. The strange thing is that the previous version of the website used the same exact piece of code for the buttons and it worked.
  6. A precious hint came from the fact that for generating meta tags for socials I was accessing the property this.$nuxt.$route.params.blogEntry (on a page called _blogEntry.vue), and noticed that the returned value during the generate process was set once and then never changed. I fixed the _blogEntry.vue problem by saving the article url inside the asyncData returned object.
  7. Applying the same logic in the home page, I changed the condition on the button elements from v-if="$nuxt.$route.path.indexOf('blog') < 0" to v-if="$route.path.indexOf('blog') < 0" and, after executing another round of generate, the page worked perfectly.

Unfortunately I cannot provide a reproduction due to a lack of time right now, so sorry 'bout that.

Anyway I think the problem is that when generateing the static app, $nuxt values are not correctly updated for some reason. I do not even know if this kind of behavior is wanted and well known or not, even though I doubt it.

Hope this can help somebody.

Closing here as there are a couple of reasons why the state of the HTML and the state of the client are out of sync and there isn’t much we can do against that right now besides debugging. The error is most likely related to Vue Hydration failing and tough to spot.

A few of the error source have been mentioned throughout this issue, others can be found in this blog post.

Feel free to investigate further but from the side of the core team there isn’t much to “solve”.

Vue3 will bring improved hydration and hopefully also improvements in this area ☺️

But the problem is really because of async server auth module. If use <client-only><div v-if="$auth.loggedIn"><div/></client-only>, then the problem disappears

@willin Not sure if its a matter of your English skills, but saying just fix it is not a nice thing to say. Please have a look at Nuxt’s Code of Conduct

I still dont understand what you are trying to do, normally you shouldnt have to manually change the ssr property so the only issue I see is a documentation thing to better clarify that. Again, please remove ssr: false from your config and then run nuxt generate as with what you have explained up to now that should do exactly what you need. Otherwise explain in full detail what you are trying to accomplish.

The video could be useful, but really, the only concrete way to solve your issue is by providing a reproducible example, else it’s just a hunt in the dark. “the devil is in the details”

I would suggest a https://codesandbox.io/, filddle, or whatever other platform you like.

Without a concrete reproducible example, as per the “need repro” label on the issue, I don’t know how the core team will be able to help you?

I solved my problem: If I use v-show instead of v-if, the issue disappears.

<div v-if="$auth.loggedIn"> --> <div v-show="$auth.loggedIn">

See https://github.com/nuxt/nuxt.js/issues/1552#issuecomment-356584010

In case this helps save someone some grief, I just dealt with this issue for hours. Tried absolutely everything:

deleting node_modules and reinstalling, deleting .nuxt folder, switched dev/prod mode, clearing cookies and localstore, refreshing…

In the end it turned out to be aggressive browser cache. The only thing that worked was hard reloading the browser:

Screenshot from 2020-03-26 09-46-35

Worth a try if you’ve done everything! it worked for me 😃

Does anyone have issue when you try to use v-if=this.$auth.user for conditional rendering?

Almost all of the time, the app is showing DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.

However, if you move pages with a certain way, the app is working properly as intended…

Any followups?

I had the same issue, my component didn’t load I use next solution:

    <template lang="html">
       <div v-if="mounted">
            ......
           <my-component />
       </div>
    </template>
    
     <script>
        export default {
            data() {
               mounted: false
             }
        },
       mounted() {
         setTimeout(() => {
            this.mounted = true;
       }, 10)
     }
    </script>

Here is how I fixed it:

yarn add gulp gulp-html-minifier

then create gulpfile.js

const { src, dest } = require('gulp')
const htmlmin = require('gulp-html-minifier')

function minify() {
  return src('./dist/**/*.html')
    .pipe(htmlmin({ removeComments: true, collapseWhitespace: true }))
    .pipe(dest('./dist'))
}

exports.default = minify

in package.json for generate script do this: nuxt generate && gulp

Thanks for this. I have tried everything, only your method works!

Thanks @rstormsf, I can confirm that this fixed the issue for me. No longer getting this error after generating and deploying to production. Thumbs up!

If someone indeed can support by providing a repro build, I hope that it can be fixed within Nuxt itself.

Suppose you have a index.vue like this and also use @nuxtjs/auth:

<template>
<div>
  <div v-if="loggedIn">
     ....
  </div>
  <nuxt-link v-else to="/login">
     Login
  </nuxt-link>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  auth: 'false',
  computed: {
    ...mapState('auth', ['loggedIn']),
  },
}
</script>

Prerequiste is generating the app via nuxt generate and deploying it (in our case netlify).

With mode: 'universal' set in nuxt.config.js: If you are logged in and call the '/' route manually, you won’t see the div and instead the Login link, and also get the appendChild error in console.

If you navigate to the '/' route from inside the app, this error also doesn’t show up. It’s just on a full page refresh.

With mode: 'client' you don’t get this error and you see the loggedIn div.

@willin but thats not minimal, that seems to be a full project with custom components etc. Also its not on codesandbox so I have to clone it myself, install deps and then try to understand what all those components do to see if they have an impact or not. I am just too lazy for that because previous issues have shown that 9 out of 10 times its a user issue and not a nuxt issue.

That said I am willing to believe that this might be a Nuxt issue because multiple users reported it, but still please make it as easy as possible for us so we dont have to spent 5-10 minutes on every reported issue to setup the reproduction environment. Help us to help you, thanks :bowtie:

Same issue on a very simple page, I will see if I can pinpoint the issue.

… it’s not i guess. @manniL

i tried

npx create-nuxt-app demo-framework

and use vuetify, can run successfully.

then. i add config build - ssr - to false then auto refresh and refresh … endless

perhaps it’s a bug about ssr and generate…

I’ve methodically gone through each of my components one at a time, and have found something interesting. The issue occurs for me if i have <template> tags with nothing inside them, for instance here is some working code

<div class="column" v-for="(card, index) in cards">
     <template v-if="card.button">
          <template v-if="card.button.type == 'page'">
                   A word typed in here
          </template>
     </template>
</div>

This code will throw the error though

<div class="column" v-for="(card, index) in cards">
     <template v-if="card.button">
          <template v-if="card.button.type == 'page'">
                   <!-- nothing in here -->
          </template>
     </template>
</div>

Because the error is erratic and inconsistent, i can repeatedly press refresh and sometimes it works sometimes it doesn’t without following any particular pattern, it appears it’s something to do with timing. That when the v-if computes and tries to append the dom element, the parent element is still a comment tag and can’t be appended to.

As @nekdolan and @Splinterjke pointed out, using v-if with a $vuetify.breakpoint breaks with SSR. Since v-if removes the DOM element (making the mismatch happen between client and server), my solution was to simply switch to using a v-show since the DOM element remains, but is hidden.

Example:

<v-app-bar-nav-icon
  v-show="$vuetify.breakpoint.smAndDown"
  @click.stop="input()"
/>

I think that’s because $vuetify.breakpoint relies on BOM. The viewport width is not available on the server side. In such case, you can also use <client-only> to wrap the element.

As @nekdolan and @Splinterjke pointed out, using v-if with a $vuetify.breakpoint breaks with SSR. Since v-if removes the DOM element (making the mismatch happen between client and server), my solution was to simply switch to using a v-show since the DOM element remains, but is hidden.

Example:

<v-app-bar-nav-icon
  v-show="$vuetify.breakpoint.smAndDown"
  @click.stop="input()"
/>

@cyrrill Thank you, you saved me hours!

I got this error when I tried to do v-if="$vuetify.breakpoint.smAndDown" in Universal mode. Makes sense, but a more informative error might be a good idea, if at all possible.

DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.

Faced this issue too. Google Analytics broke layout while switching between pages. It was decided by adding script to <no-ssr> tag

Hello,

Repro available here: https://github.com/iiAku/repro-v-if-bug

nb: I understand that my code could be smarter or written another way, but this is basically a piece of code that was not working and I did perhaps misunderstood how vue conditional rendering is working.

ping @pimlie @Atinux

Note for @alisonmoura and others, as suggested by @pimlie , please comment if you have extra details for the issue or repro link.

Thanks for your time.

Hello, That time seems to be the good one. Quick note about @BigFly3 's answer: it also would have been great if you had given more details about how to achieve this. I’m happy with this if you managed to make it work for that way. However just to clarify and give a little bit more pieces of advices for the otherpeople who ran into the same issue and want to give it a try to your explained solution. You are using the internal hooks mechanism from Nuxt.js where documentation is available there: https://nuxtjs.org/api/internals-generator#hooks This need to be declared into your nuxt.config.js file as a new property in the exported object. Also you are using pretty which is not an internal tool and available from there: https://www.npmjs.com/package/pretty That means obviously you’ll have to add it as dependency and import it earlier for using it through the nuxt.config.js.

After going forward on my project and trying to fix this, it leads that my issue was linked to a conditional rendering see this: https://vuejs.org/v2/guide/conditional.html That’s perhaps a beginner issue but I just realised while troubleshooting (correct me if I’m wrong) that you can’t have nested conditional rendering with vue.js. You cannot nest multiple v-if or mixed v-if/v-show. I did have a v-if nested into another v-if and it was basically what was doing the mismatch between the expected DOM node and the rendered one. I also managed to get the error message and a more explicit one on dev side, so thanks Nuxt.js community. Actually what I figured it out seems narrowly linked with upper solution saying to turn v-if statement into v-show. However I wanted to understand the underlying reason regarding this. In the end this is with what I ended up for that particular case. However it does not means you have to use v-show instead of v-if at all time. As explained here: https://vuejs.org/v2/guide/conditional.html#v-if-vs-v-show v-show is about dom element visibility where v-if completely remove the block/functionalities from the DOM, so it remains still useful on the vast majority of case regarding conditional rendering.

As some pieces of advice for those who are facing that issue, I’ll recommend to spend time on the following points:

  1. Identifying which part of your app is generating that issue, in order to reduce the scope of troubleshooting
  2. Making sure you are not using any kind of nested v-if/v-show
  3. Making sure you are using valid HTML template into your vue components (formatting/linting can help)

While going through this I believe you should not face any kind of DOMException error in dev/prod Nuxt.js app.

Enjoy.

@rstormsf Thank you so much, fixed it for me. Why does Gulp fix it??

So instead of:

sessionStorage.getItem('xxx')

Use:

if (process.client) {
  return sessionStorage.getItem('xxx')
} else {
  return where-to-get-the-same-value-or-a-placeholder-on-the-server
}

This would sometimes happen when im using asyncData with a lazy loaded component. If the component is not lazy loaded then it starts working.

Just remove ssr: false from your config and run yarn generate. That will generate html files and resources for all the static routes and the dynamic routes you have provide with generate.routes in your config.

Thank you very much for the minimal repro.

What is your use-case for setting ssr: false but not using mode: spa? Its recommended to just use either mode: universal or mode: spa. You can do this with a cli option as well, run yarn generate -s to generate your site in spa mode or just yarn generate to generate in universal mode. See yarn nuxt --help for a list of available options