Failed to execute ‘removeChild’ on ‘Node’

I had to deal with the same issue, and the answer is confusing and counter intuitive. Well, it has its logic, but leads to non-trivial behaviours.

Essentially, when a node is removed from the DOM tree, it fires a blur event (and before a focusout event too).

So, when you call removeChild, the blur event is fired again, but this time textarea still has its parentNode defined, but textarea isn’t among its parent’s children anymore! (Yes, read this twice. Or more.)

This happens in Chrome for now, although Firefox has planned to do the same for quite some time.

As a workaround, you can remove the event listener you attached:

var onblur = function(e) {
    detachEvent(textarea, 'blur', onblur);
    textarea.parentNode.removeChild(textarea);
    removeClass(highlighterDiv, 'source');
};
attachEvent(textarea, 'blur', onblur);

I’m assuming that you have some detachEvent function to remove event listeners. Adjust the code to your needs.

Alternatively, you can set a flag (like a property, or an attribute, or better a scoped variable) on the textarea in the listener function, and check for it before proceeding with the node removal:

var removed = false;
attachEvent(textarea, 'blur', function(e) {
    if (removed) return;
    removed = true;
    textarea.parentNode.removeChild(textarea);
    removeClass(highlighterDiv, 'source');
});

You can also check if textarea if actually a child node of its parentNode before removing it, but such test is so counter-intuitive (at least to me) that I wouldn’t recommend doing that, in fear that this behaviour will be changed in the future.

Finally, you can always rely on a try...catch statement, but… ugh.

2016 Update

Naturally, using a framework like jQuery would save you a lot of work attaching event listeners with one, but this functionality will come to standard addEventListener too:

textarea.addEventListener('blur', handler, { once: true });

Leave a Comment