Gatsby: Pages not deleted on node update/delete

Created on 5 Jan 2019  路  8Comments  路  Source: gatsbyjs/gatsby

Description

When pages are created from nodes, and you use the createPageDependency() action to declare a dependency on the node, when the node is deleted (after the first build), no page rebuilding is triggered. The change is visible once something else triggers a page rebuild, but the page is not removed.

A similar thing happens when you update a node which causes a new page to be built: the node is updated, but the page building fails with this error:

Error loading a result for the page query in "/updated-title-of-post-3". Query was not run and no cached result was found.
Page not found /updated-title-of-post-3 

Steps to reproduce

I've create a sample repo where you can easily reproduce both bugs. See https://github.com/rexxars/gatsby-node-update-bugs

Expected result

I had expected that the page would be marked as dirty and thus removed. In the case of the updated node, I would have expected the new page to work as intended, while the old page would be removed.

Actual result

As outlined in the description, the pages never seem to be removed, and new pages builds with errors.

Environment

  System:
    OS: macOS 10.14.2
    CPU: (8) x64 Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
    Shell: 4.4.12 - /usr/local/bin/bash
  Binaries:
    Node: 10.8.0 - ~/.nvm/versions/node/v10.8.0/bin/node
    Yarn: 1.12.3 - ~/.nvm/versions/node/v10.8.0/bin/yarn
    npm: 6.4.1 - ~/.nvm/versions/node/v10.8.0/bin/npm
  Browsers:
    Chrome: 71.0.3578.98
    Firefox: 64.0
    Safari: 12.0.2
  npmPackages:
    gatsby: ^2.0.76 => 2.0.85 
  npmGlobalPackages:
    gatsby-cli: 2.4.7
not stale confirmed bug

Most helpful comment

I believe that the problem here occurs in the query-runner module. In that module, a call is made to the store to retrieve the page that needs to be modified, and that page is then fed into the pageDataUtil:

      const page = pages.get(queryJob.id);
      await pageDataUtil.write({
        publicDir
      }, page, result);

If the page has been deleted, the pages.get call returns undefined and the pageDataUtil is sent garbage.

All 8 comments

Thank you for opening this @rexxars

no page rebuilding is triggered. The change is visible once something else triggers a page rebuild, but the page is not removed.

Just so I understand correctly, when you say _the page is not removed_, you mean the assets still exist in public?

  1. You have add a node through createNode() of type blogPost.
  2. Gatsby calls createPages()

    • A query is run to fetch all blog posts

    • A page is created from the given blog post

    • createPageDependency() binds the page and the blog post node

  3. At some point later, the blog post node is deleted through deleteNode()
  4. Nothing happens. createPages() is not called, so the page referencing the node still lingers. You can still navigate to it, and if you go to the 404 page which lists generated pages, it is listed.

The expected result is that createPages() is called, the node is no longer returned by the query, and the node (and page) is marked dirty and removed. Correct me if I'm wrong, obviously.

The repository I linked to should illustrate this problem quite easily.

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 馃挭馃挏

I believe I'm running into the same issue. When trying to exclude draft posts from the production build with

exports.onCreateNode = ({ node, actions }) => {
  if (
    process.env.NODE_ENV === `production` &&
    node.frontmatter &&
    node.frontmatter.draft
  ) {
    actions.deleteNode({ node })
  }
}

gatsby build fails after source and transform nodes with TypeError: Cannot read property 'internal' of undefined.

@janosh This is different issue. Issues listed here don't result in actual hard crashes and focus mainly on stateful source plugins that create, modify and delete nodes outside of sourceNodes API extension point.

Even if Your example didn't crash - we will probably restrict usage of it (deleting nodes that other plugins created). Better way would be to adjust your queries to filter out draft nodes from results.

Oh I see. Sorry for the confusion. I tried filtering out draft nodes at first but I don't think that's a better idea. It turned out to be quite the hassle. I first had to modify gatsby-node to not create pages for those nodes, then modify my blog page to not list excerpts of draft posts, and finally exclude those posts from the list of tags in a third component so as not to get erroneous counts for the number of posts for each tag. At that point I decided there must be a better to handle this in one place rather than all over my project.

I'm not sure if what I'm running into is the same issue or not but it may be.
I'm attempting to remove pages by deleting the nodes used to create those pages. The page is no longer SSR'ed after deleting the node it was created from, but when you visit the page you get a flash of the 404 page which gets replaced by the deleted page. This is happening in development and production.

So now I'm attempting to manually delete the page in sourceNodes using the deletePage action but I get an error: Cannot read property 'send' of undefined

Is there currently a way to manage this manually to get around the bug?
Would using createPagesStatefully work?

Edit: To add to my comment above, if I manually go into public/${pageDir}/ and delete page-data.json, the page is fully deleted. Seems like Gatsby is deleting pages where the node no longer exists, but the page data isn't being removed when it should.

You can see this bug using gatsby-source-wordpress by building Gatsby pages from WordPress page nodes, then make one of your pages into a draft and run your build again. The drafted page won't be pulled during sourceNodes but the data will still exist for the page, and if you visit the page you'll see it load in after the 404 page loads.

I believe that the problem here occurs in the query-runner module. In that module, a call is made to the store to retrieve the page that needs to be modified, and that page is then fed into the pageDataUtil:

      const page = pages.get(queryJob.id);
      await pageDataUtil.write({
        publicDir
      }, page, result);

If the page has been deleted, the pages.get call returns undefined and the pageDataUtil is sent garbage.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

totsteps picture totsteps  路  3Comments

jimfilippou picture jimfilippou  路  3Comments

dustinhorton picture dustinhorton  路  3Comments

mikestopcontinues picture mikestopcontinues  路  3Comments

theduke picture theduke  路  3Comments