Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

warn Non-deterministic routing danger: Attempting to create page: [...] already exists

I finished writing a small blog application using Gatsby and React. Everything works fine when I try it locally. So I proceed with gatsby build and deploy the build folder into Netlify. However, after the deployment, the content of some of the pages is not shown despite locally everything works fine.

Description of the problem: I have a navbar with "Home", "Healthcare", "Technology", "Robotics", "Posts", "NewsLetter", and every time a user clicks on for example "Robotics" a series of posts from that category is shown. Now locally everything works fine but as soon as I deploy I can only see "Posts" page which carries all the posts. The other choices from the navbar are not rendering the other posts categories.

Below the error I am getting from the terminal:

warn Non-deterministic routing danger: Attempting to create page: "/healthcare/", but page "/healthcare" already exists This could lead to non-deterministic routing behavior

warn Non-deterministic routing danger: Attempting to create page: "/robotics/", but page "/robotics" already exists This could lead to non-deterministic routing behavior

warn Non-deterministic routing danger: Attempting to create page: "/technology/", but page "/technology" already exists This could lead to non-deterministic routing behavior

This leads me to think that some pages are not rendered at the proper time, however, this does not explain the difference between localhost perfectly working and the deployed version not working properly.

Below my gatsby-node.js

const path = require('path')
// create pages dynamically
exports.createPages = async ({ graphql, actions }) => {
 // from actions we can destructure createPage
  const { createPage } = actions
   // below we will be running two queries at the same time 
   // instead of one query only
  const result = await graphql(`
    {
      allMdx {
        nodes {
          frontmatter {
            slug
          }
        }
      }
      category: allMdx {
        distinct(field: frontmatter___category)
      }
    }
  `)

  result.data.allMdx.nodes.forEach(({ frontmatter: { slug } }) => {
    createPage({
      path: `/posts/${slug}`,
      component: path.resolve(`src/templates/post-template.js`),
      context: {
        slug,
      },
    })
  })
  result.data.category.distinct.forEach(category => {
    createPage({
      path: `/${category}`,
      component: path.resolve(`src/templates/category-template.js`),
      context: {
        category,
      },
    })
  })
}

Below is also the file post-template.js

const PostTemplate = ({data}) => {
  const {
    mdx: {
      frontmatter: {title, category, image, date}, 
      body,},
    } = data;

  return ( 
  <Layout>
    <Hero/>
    <Wrapper>
      {/* post info */}
      <article>
        <Image fluid={image.childImageSharp.fluid} />
        <div className="post-info">
          <span>{category}</span>
          <h2>{title}</h2>
          <p>{date}</p>
          <div className="underline"></div>
        </div>
        <MDXRenderer>{body}</MDXRenderer>
      </article>
      {/* banner */}
      <article>
        <Banner/>
      </article>
    </Wrapper>
  </Layout>
  )
}


export const query = graphql`
  query GetSinglePost($slug: String) {
    mdx(frontmatter: {slug: {eq: $slug}}) {
      frontmatter {
        title
        category
        date(formatString: "MMMM Do, YYYY")
        image {
          childImageSharp {
            fluid {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
      body
    }
  }
`
const Wrapper = styled.section`
// style goes here ...
`

export default PostTemplate

and the file category-template.js

const CategoryTemplate = props => {
  console.log(props);
  const {
    pageContext: { category },
  } = props;

  const {
    data: {
      categories: {nodes:posts}
    }
  } = props;

  return (
    <Layout>
      <Hero/>
      <Posts posts={posts} title={`category / ${category}`}/>
    </Layout>
  )
}

export const query = graphql`
  query GetCategories($category: String) {
    categories: allMdx(sort: {fields: frontmatter___date, order: DESC}, filter: {frontmatter: {category: {eq: $category}}}) {
      nodes {
        excerpt
        frontmatter {
          title
          author
          category
          date(formatString: "MMMM, Do, YYYY")
          slug
          readTime
          image {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
        id
      }
    }
  }
`
export default CategoryTemplate

Below the structure of the robotics page component (all the other page components healthcare and technology have the same exact structure so I am only including one)

robotics.js

const robotics = () => {
    return (
        <Layout>
            <SEO title="Robotics"/>
            <Hero />
            <h2>robotics page</h2>
        </Layout>
    )
}

export default robotics

In order to solve this problem I did a lot of research but before I would like to pint out that I already clean and redeploy the same application a couple of times before. So what I tried so far:

  1. sudo gatsby clean && sudo gatsby develop after it was working I did sudo gatsby build

After deploying the build folder some pages were not rendering properly so I:

  1. sudo m -rf node_modules sudo rm -rf public/ and sudo rm -rf package-lock.json and procedeed with:
  2. sudo npm install (if necessary you have to do sudo nom install --unsafe-perm) and
  3. sudo gatsby develop && sudo gatsby build

But unfortuantely the same exact outcome: localhost everthing works fine and on Netlify some pages were not rendering at all.

So I did additional research and I studied this post which represents the same exact problem I have. Unfortunately no answer was accepted. But I tried to apply the suggestion and in fact on my gatsby-node.js I had:

exports.createPages = async ({ graphql, actions, reporter }) => {
  const yourQuery= await graphql(
          `
            {
              parameters here
            }
          `
  if (yourQuery.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`);

    return;
  }

But nothing happened.

I studied this and this too. This post says that "MDX pages cant currently be in the same directory as JSX pages" but I am not sure this is accurate and did not see it in the official documentation an example showing not to do that.

Please guide me to a potential solution on this point.

like image 550
EsoMars Avatar asked Mar 01 '21 17:03

EsoMars


1 Answers

Your issue relies on the naming, and I assume that it will affect all pages (robotics, healthcare, technology, etc). This:

const robotics = () => {
    return (
        <Layout>
            <SEO title="Robotics"/>
            <Hero />
            <h2>robotics page</h2>
        </Layout>
    )
}

export default robotics

Should be:

const Robotics = () => {
    return (
        <Layout>
            <SEO title="Robotics"/>
            <Hero />
            <h2>robotics page</h2>
        </Layout>
    )
}

export default Robotics

Notice the capitalized component (Robotics). This is because, in React, all component names must be capitalized otherwise, React's assignation will never work.

The rest of the code, without a CodeSandbox it's difficult to check but it looks good.

In addition, something that can also lead to this behavior is the use of plugins such as gatsby-plugin-remove-trailing-slashes, so double-check that if you are using it.


Outside the scope of the question (and because of sudo gatsby develop && sudo gatsby build) it seems that you don't know the difference between gatsby develop and gatsby build, they are not complementary and it doesn't make sense to use that command.

To summarize, gatsby build creates a version of your site with production-ready optimizations like packaging up your site’s config, data, and code, and creating all the static HTML pages that eventually get rehydrated into a React application.

gatsby develop just runs a server in the background, enabling useful features and it is optimized for rapid feedback and extra debugging information. It doesn't bundle and compile your code production environment, potentially hiding some issues that will appear in Netlify, since it runs gatsby build.

With that command, you are developing your site and quitting the process by running the gatsby build, without serving it.

So, to double-check your site before pushing it to Netlify, I would suggest running a gatsby build && gatsby serve locally, since, if the Node versions in Netlify and locally are the same, the project must behave equally in both environments.

You can read the Gatsby docs for further explanations.


I did additional research and I studied this post which represents the same exact problem I have. Unfortunately no answer was accepted.

I answered that question. The error output may be the same but it's caused but a completely different use-case. In that case, the issue relies on a wrong/unfinished promise approach, and it only affects the dynamic pages, in your case are the opposite. In your scenario, the "static" pages are the problem due to bad naming because React can't resolve the component assignation.

like image 168
Ferran Buireu Avatar answered Sep 19 '22 00:09

Ferran Buireu