`gatsby develop` crashes every time a blog entry is changed

Viewed 928

Using the Flexible Gatsby starter (https://github.com/wangonya/flexible-gatsby/), exact versions of Gatsby dependencies are:

    "gatsby": "2.15.36",
    "gatsby-image": "2.2.27",
    "gatsby-plugin-feed": "2.3.15",
    "gatsby-plugin-google-analytics": "2.1.20",
    "gatsby-plugin-manifest": "2.2.20",
    "gatsby-plugin-offline": "3.0.12",
    "gatsby-plugin-react-helmet": "3.1.10",
    "gatsby-plugin-sass": "2.1.17",
    "gatsby-plugin-sharp": "2.2.28",
    "gatsby-remark-images": "3.1.25",
    "gatsby-remark-prismjs": "3.3.17",
    "gatsby-source-filesystem": "2.1.30",
    "gatsby-transformer-remark": "2.6.27",
    "gatsby-transformer-sharp": "2.2.20",

I can run gatsby develop to get a watch on the files in the folder that refreshes UI changes and such. However, as soon as I save any changes to any of the files in content/blog develop hits the following error:

info added file at /Users/mattsi/dev/me/newsite/gatsby/content/blog/conference-on-javascript/index.md

 ERROR #11321  PLUGIN

"gatsby-node.js" threw an error while running the createPages lifecycle:

The "path" argument must be of type string. Received type undefined

GraphQL request:14:17
13 |                 title
14 |                 img {
   |                 ^
15 |                   childImageSharp {

After that, the local server responds with an error page saying TypeError: Cannot read property 'page' of undefined and a stack trace pointing to rootjs:44. If I kill the watch and do gatsby develop again, it works fine. But that feedback loop is obviously much slower.

My Gatsby Config (some details omitted with ...):

module.exports = {
  siteMetadata: {
    title: `...`,
    description: `...`,
    author: `...`,
    siteUrl: `...`,
    social: {
      twitter: `...`,
      facebook: ``,
      github: `...`,
      linkedin: `...`,
      email: `...`,
    },
  },
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/blog`,
        name: `blog`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/assets`,
        name: `assets`,
      },
    },
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 970,
            },
          },
          `gatsby-remark-prismjs`,
        ],
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        //trackingId: `ADD YOUR TRACKING ID HERE`,
      },
    },
    `gatsby-plugin-feed`,
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `...`,
        short_name: `...`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `./static/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
    // `gatsby-plugin-offline`,
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-sass`,
  ],
}

My gatsby-node.js file:

const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions

  const blogPost = path.resolve(`./src/templates/blog-post.js`)
  return graphql(
    `
      {
        allMarkdownRemark(
          sort: { fields: [frontmatter___date], order: DESC }
          limit: 1000
        ) {
          edges {
            node {
              fields {
                slug
              }
              frontmatter {
                title
                img {
                  childImageSharp {
                    fluid(maxWidth: 3720) {
                      aspectRatio
                      base64
                      sizes
                      src
                      srcSet
                    }
                  }
                }
              }
            }
          }
        }
      }
    `
  ).then(result => {
    if (result.errors) {
      throw result.errors
    }

    // Create blog posts pages.
    const posts = result.data.allMarkdownRemark.edges

    posts.forEach((post, index) => {
      const previous = index === posts.length - 1 ? null : posts[index + 1].node
      const next = index === 0 ? null : posts[index - 1].node

      createPage({
        path: post.node.fields.slug,
        component: blogPost,
        context: {
          slug: post.node.fields.slug,
          previous,
          next,
        },
      })
    })

    // Create blog post list pages
    const postsPerPage = 10
    const numPages = Math.ceil(posts.length / postsPerPage)

    Array.from({ length: numPages }).forEach((_, i) => {
      createPage({
        path: i === 0 ? `/` : `/${i + 1}`,
        component: path.resolve("./src/templates/blog-list.js"),
        context: {
          limit: postsPerPage,
          skip: i * postsPerPage,
          numPages,
          currentPage: i + 1,
        },
      })
    })
  })
}

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    createNodeField({
      name: `slug`,
      node,
      value,
    })
  }
}

Looking into the stack trace, it seems as if the post.node.fields.slug field on the modified post from the allMarkdownRemark GraphQL DB is coming back as undefined. But using the built-in GraphQL browser it seems to always be populated. Perhaps it's very briefly unpopulated while refreshing, faster than I can catch, and this causes the watch to crash? Any ideas how I can fix Gatsby's watch functionality?

1 Answers

I have this issue too and I believe it will be fixed by this PR - it was for me at least. Perhaps you could test it out and comment on the PR if it helps you.

Related