Lit-html: Uncaught (in promise) TypeError: Cannot read property 'nextSibling' of null

Created on 15 Mar 2018  ·  22Comments  ·  Source: Polymer/lit-html

I've got a LitElement with render method:

render({restaurantId}) {
  const restaurantView = restaurant => html`
    <restaurant-view restaurant="${restaurant}">
      ${fetchReviews(restaurantId).then(reviewsList)}
    </restaurant-view>
  `;

  const restaurantList = restaurants => html`
    <restaurant-list restaurants="${restaurants}"></restaurant-list>
  `;

  const restaurant = fetchRestaurantById(restaurantId).then(restaurantView);
  const restaurants = fetchRestaurants().then(restaurantList);

  return restaurantId
    ? html`${until(restaurant, restaurantView())}`
    : html`${until(restaurants, restaurantList([]))}`;
}

When I load up a restaurantId, I get the following error:

lit-html.ts:776 Uncaught (in promise) TypeError: Cannot read property 'nextSibling' of null
    at removeNodes (lit-html.ts:776)
    at NodePart.clear (lit-html.ts:665)
    at NodePart._setNode (lit-html.ts:563)
    at NodePart._setTemplateResult (lit-html.ts:592)
    at NodePart.setValue (lit-html.ts:542)
    at value.then (lit-html.ts:659)
removeNodes @ lit-html.ts:776
clear @ lit-html.ts:665
_setNode @ lit-html.ts:563
_setTemplateResult @ lit-html.ts:592
setValue @ lit-html.ts:542
value.then @ lit-html.ts:659
Promise.then (async)
_setPromise @ lit-html.ts:657
setValue @ lit-html.ts:548
directive @ until.ts:23
getValue @ lit-html.ts:405
setValue @ lit-html.ts:530
update @ lit-html.ts:710
render @ lit-html.ts:177
_propertiesChanged @ lit-element.js:113
_flushProperties @ properties-changed.js:307
ready @ properties-changed.js:151
ready @ lit-element.js:79
_enableProperties @ properties-changed.js:287
connectedCallback @ properties-mixin.js:176
(anonymous) @ restaurant-reviews.js:117
Show 2 more blackboxed frames

Immediately after this exception, my view renders properly. Attempts to track down bugs in my own code that could cause this have so far turned up nothing. Perhaps consider a more verbose exception.

Thanks for considering this issue

Medium Bug

Most helpful comment

+1 this issue is affecting IE11 heavily.
A (simple) work around is to put the offending nodes into a new ShadyDOM, obviously a solution like that is less than ideal and could result in a significant performance hit.

All 22 comments

+1
I got this error when tried to implement filter search which used .repeat to render and iterate the result array. When update the result multiple times it throw out error 'Cannot read property 'nextSibling' of null'. I've to work around by using .map instead to iterate the item.

@jukbot it's possible you saw the same error, but for a different cause. Can you add a reproduction?

@justinfagnani Also noticing this same error message for every one of my tests.

Test (Mocha in browser)

it('should have a value set', () => {
    render(html`<text-input .value=${'Hello World'}></text-input>`, TEST_CONTAINER);
    const input = TEST_CONTAINER.querySelector('text-input') as any;
    assert.strictEqual(input.value, 'Hello World', 'Should have a value of Hello World');
    TEST_CONTAINER.clear();
  });

Webpack literal source

it('should have a value set', () => {
        Object(lit_html__WEBPACK_IMPORTED_MODULE_1__["render"])(lit_html__WEBPACK_IMPORTED_MODULE_1__["html"] `<text-input .value=${'Hello World'}></text-input>`, TEST_CONTAINER);
        const input = TEST_CONTAINER.querySelector('text-input');
        assert__WEBPACK_IMPORTED_MODULE_2__["strictEqual"](input.value, 'Hello World', 'Should have a value of Hello World');
        TEST_CONTAINER.clear();
    });

Error message

TypeError: Cannot read property 'nextSibling' of null
    at removeNodes (webpack:///./node_modules/lit-html/lib/dom.js?:41:24)
    at NodePart.clear (webpack:///./node_modules/lit-html/lib/parts.js?:291:68)
    at NodePart._commitNode (webpack:///./node_modules/lit-html/lib/parts.js?:203:14)
    at NodePart._commitTemplateResult (webpack:///./node_modules/lit-html/lib/parts.js?:234:18)
    at NodePart.commit (webpack:///./node_modules/lit-html/lib/parts.js?:180:18)
    at render (webpack:///./node_modules/lit-html/lib/render.js?:46:10)
    at Context.it (webpack:///./dist/test/elements/forms/text-input.test.js?:11:64)

This is just one of the tests that is failing, but this occurs for all 19 tests after the first one.

For completion the TEST_CONTAINER.clear() method is just a .innerHTML = ''; to clear the elements for insertion of the next test.

Interesting note: This only affects tests after the first one. The first one always succeeds even though it is of identical structure and composition. This feels like an issue with the cleanup of the previous test is leaking into the subsequent tests, or something is putting lit-html into a bad state that causes it to fail all renders after that point? Just guesses at this point.

What version of lit-html are you using @SnareChops ?

@ruphin 0.11.3

@ruphin Another interesting note, rolling back to 0.11.2, everything succeeds. Perhaps a bug introduced in 0.11.3?

Then it is caused by modifying the content of the container directly by using innerHTML. If you use lit-html to render to a container, you should never manually edit its content. You can either use lit-html instead of innerHTML to clear the content (render('', TEST_CONTAINER)), or use a new container for each test.

@ruphin Ok I'll give that a shot. Thanks

It's not a bug, it's a side effect of a change in the implementation of render(). As a rule you can never directly edit something that was rendered by lit-html without risking breaking it. That it didn't break before was basically just by chance.

We're working on a change that will fix the breakage for your specific usecase, but there's no guarantee it won't break again in the future.

As a rule, you should never manually manipulate any html that was rendered by lit-html. If you do, there's a reasonable chance that you break future renders. Use lit-html to change what you want

Please also consider my posting on stackoverflow
https://stackoverflow.com/questions/52339496/lit-element-uncaught-in-promise-typeerror-cannot-read-property-previoussib
I get the same error when using webcomponents-loader.js
If I use webcomponents-bundle.js instead, I get the following :
Uncaught (in promise) TypeError: Cannot read property 'previousSibling' of null

Could it be related to webcomponents in some ways ? Because as I mentioned in my post, changing from one script to the other is triggering a different issue. And loading the webcomponents loader script cause shady-render.ts to throw a warning even though I have the proper versions (of both webcomponents.js and shadycss.js).

Switching to lit-html version 0.11.2 as @SnareChops mentioned worked out for me as well.

And as you mentioned @ruphin one rule of thumb is not to manipulate the html produced by lit-html but I am not. Mainly because I am using (and have updated) lit-element version 0.6.0. lit-element gives enough templating functionality not to worry about subsequent dom manipulations. Could it also be related to lit-html causing these errors itself as the problem seemed to be caused by the repeat directive too (@jukbot case and mine).

There is a known issue with ShadyCSS that was introduced in 0.11.3, so that may be causing your problems with shady-render. I think the fix is already in so it should be resolved with 0.11.4

If you are using LitElement, you should probably be using lit-html version 0.11.2, which is what lit-element itself uses. Otherwise there's a reasonable chance that you are using two different versions, which may also explain some problems.

I can't reproduce your issues though: https://codepen.io/ruphin/pen/qMyMVO?editors=1010

The only explanation I can come up with is that webcomponents-bundle.js works, which triggers ShadyRender to be used, which breaks. When you switch to webcomponents-loader.js the polyfills don't work for some reason, which causes ShadyRender to not be used and explains why you don't get the error, but get the incompatible polyfill warnings, and don't get properly polyfilled CSS. I don't know why this is happening though, both versions of the polyfill should work, although I generally recommend using -bundle.

It would help if I knew on what browser/version you are seeing the problem.

I've temporarily set-up the broken application online : http://hanmun.vdegenne.com/가
Some parts of the layout are broken because the @apply directives are not properly rendered. For instance in the app-bar the logo should be in the middle and the search-icon on the right.
Anyway, the point is that you should see the warning in the console.

versions :

As a rule, you should never manually manipulate any html that was rendered by lit-html. If you do, there's a reasonable chance that you break future renders. Use lit-html to change what you want

@ruphin I guess changing contents of rendered elements with contenteditable=true also qualifies here? I have the same error when I edit contents of an editable element and then try to re-render it.

I've determined this error happens in browsers with ShadyCSS when there's a dynamic content before or after <style> tag.

This works in all browsers:

html`<style>.name { color: white; }</style><h1>${this.title}</h1>`

This breaks when ShadyCSS polyfill is used:

html`<style>.name { color: white; }</style>${this.title}`

I am also seeing this with the use of until, when the template with until was shown briefly and was subsequently replaced with a non-until template.

I managed to reproduce in a Plunkr for [email protected]

https://next.plnkr.co/edit/PDiAVDdvnK1vsWzY

Excellent demo. I've reduced it further at https://output.jsbin.com/kaneruq/quiet.

It boils down to the TempaltePart holding onto disconnected nodes, and the ! assertion on startNode.parentNode!: https://github.com/Polymer/lit-html/blob/04a30abb010b4e0d8abec1b2ca411b127d8a06e0/src/lib/parts.ts#L333.

But, we disconnect this TemplatePart, so it's startNode no longer had a parentNode.

I have recently run into this issue. @jridgewell I notice you still have an open pr which may resolve this issue, is there anything preventing the fix from getting merged?

It's just waiting for a review and merge.

+1 this issue is affecting IE11 heavily.
A (simple) work around is to put the offending nodes into a new ShadyDOM, obviously a solution like that is less than ideal and could result in a significant performance hit.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AndyOGo picture AndyOGo  ·  3Comments

justinfagnani picture justinfagnani  ·  3Comments

pjtatlow picture pjtatlow  ·  3Comments

cbelden picture cbelden  ·  4Comments

MVSICA-FICTA picture MVSICA-FICTA  ·  5Comments