Gatsby: [v2] Gatsby build failing with "WebpackError: TypeError: Cannot read property 'replace' of undefined"

Created on 12 Aug 2018  ยท  10Comments  ยท  Source: gatsbyjs/gatsby

Description

When running npm run build I get the following error:

gatsby build --prefix-paths
success open and validate gatsby-config โ€” 0.006 s
success load plugins โ€” 0.171 s
success onPreInit โ€” 0.358 s
success delete html and css files from previous builds โ€” 0.113 s
success initialize cache โ€” 0.123 s
success copy gatsby files โ€” 0.046 s
success onPreBootstrap โ€” 0.001 s
success source and transform nodes โ€” 0.283 s
success building schema โ€” 0.241 s
success createPages โ€” 0.362 s
success createPagesStatefully โ€” 0.006 s
success onPreExtractQueries โ€” 0.001 s
success update schema โ€” 0.176 s
success extract queries from components โ€” 0.077 s
success run graphql queries โ€” 0.428 s โ€” 109/109 256.00 queries/second
success write out page data โ€” 0.004 s
success write out redirect data โ€” 0.001 s
success onPostBootstrap โ€” 0.001 s

info bootstrap finished - 3.899 s

success Building production JavaScript and CSS bundles โ€” 3.447 s
โ ˆ Building static HTML for pages
error Building static HTML for pages failed

See our docs page on debugging HTML builds for help https://goo.gl/yL9lND

  584 |   // console.log({stripSlashes, str})
  585 |   // if (!str) return ''
> 586 |   return str.replace(/(^\/+|\/+$)/g, "");
      | ^
  587 | };
  588 |
  589 | var createRoute = function createRoute(basepath) {

  WebpackError: TypeError: Cannot read property 'replace' of undefined

  - index.js:586 stripSlashes
    [lib]/[@reach]/router/es/index.js:586:1

  - index.js:606
    [lib]/[@reach]/router/es/index.js:606:1

  - react.production.min.js:18 V
    [lib]/[react]/cjs/react.production.min.js:18:48

  - react.production.min.js:16 S
    [lib]/[react]/cjs/react.production.min.js:16:210

  - react.production.min.js:18 W
    [lib]/[react]/cjs/react.production.min.js:18:388

  - react.production.min.js:19 Object.map
    [lib]/[react]/cjs/react.production.min.js:19:67

  - index.js:211 RouterImpl.render
    [lib]/[@reach]/router/es/index.js:211:1

  - react-dom-server.node.production.min.js:28 d
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:28:207

  - react-dom-server.node.production.min.js:28 wa
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:28:493

  - react-dom-server.node.production.min.js:33 a.render
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:33:16

  - react-dom-server.node.production.min.js:32 a.read
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:32:201

  - react-dom-server.node.production.min.js:43 renderToString
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:43:1

  - static-entry.js:145 Module../.cache/static-entry.js.__webpack_exports__.default
    lib/.cache/static-entry.js:145:16

The development version seems to be working without any noticeable issue.

For some reason it seems that @reach/router tries to run a str.replace where str is undefined.

If I add the following line in the stripSlashes function of the router before the str.replace

if (!str) return ''

The error seems to go away and the produced build works fine.

Steps to reproduce

Under gatsby v2 run npm run build

Expected result

Build should be produced without the issue

Actual result

Error described above blocks the build

Environment

  System:
    OS: macOS High Sierra 10.13.6
    CPU: x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 10.7.0 - /Users/luciano/local/bin/node
    Yarn: 1.6.0 - /Users/luciano/local/bin/yarn
    npm: 6.1.0 - /Users/luciano/local/bin/npm
  Browsers:
    Chrome: 69.0.3497.32
    Firefox: 57.0.3
    Safari: 11.1.2
  npmPackages:
    gatsby: ^2.0.0-beta.98 => 2.0.0-beta.98 
    gatsby-plugin-catch-links: ^1.0.24 => 1.0.24 
    gatsby-plugin-feed: next => 2.0.0-beta.3 
    gatsby-plugin-google-analytics: next => 2.0.0-beta.2 
    gatsby-plugin-offline: next => 2.0.0-beta.3 
    gatsby-plugin-react-helmet: next => 3.0.0-beta.3 
    gatsby-plugin-sharp: next => 2.0.0-beta.7 
    gatsby-remark-autolink-headers: ^1.4.19 => 1.4.19 
    gatsby-remark-copy-linked-files: next => 2.0.0-beta.2 
    gatsby-remark-images: next => 2.0.1-beta.9 
    gatsby-remark-prismjs: next => 3.0.0-beta.3 
    gatsby-remark-responsive-iframe: next => 2.0.0-beta.2 
    gatsby-remark-smartypants: next => 2.0.0-beta.2 
    gatsby-source-filesystem: next => 2.0.1-beta.8 
    gatsby-transformer-remark: next => 2.1.1-beta.3 
    gatsby-transformer-sharp: ^2.1.1-beta.6 => 2.1.1-beta.6 
  npmGlobalPackages:
    gatsby-cli: 1.1.52
    gatsby: 1.9.273

File contents (if changed)

gatsby-config.js:

module.exports = {
  siteMetadata: {
    title: 'Luciano Mammino "Loige" - Web developer, entrepreneur, fighter, butterfly maker!',
    author: 'Luciano Mammino',
    description: 'The website of Luciano Mammino a.k.a. Loige, Web developer, entrepreneur, fighter, butterfly maker',
    siteUrl: 'https://loige.co/',
    twitterProfile: 'loige',
    disqusShortName: 'loige',
  },
  pathPrefix: '/',
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/posts`,
        name: 'posts',
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/speaking`,
        name: 'speaking',
      },
    },
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 1024,
            },
          },
          {
            resolve: `gatsby-remark-responsive-iframe`,
            options: {
              wrapperStyle: `margin-bottom: 1.0725rem`,
            },
          },
          'gatsby-remark-prismjs',
          'gatsby-remark-copy-linked-files',
          'gatsby-remark-smartypants',
          'gatsby-remark-autolink-headers',
        ],
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    `gatsby-plugin-catch-links`,
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        trackingId: 'UA-47248506-1',
      },
    },
    `gatsby-plugin-feed`,
    `gatsby-plugin-offline`,
    `gatsby-plugin-react-helmet`,
  ],
}

package.json:

{
  "name": "loige-co-blog",
  "private": true,
  "description": "Luciano Mammino's blog hosted on loige.co",
  "version": "1.0.0",
  "author": "Luciano Mammino",
  "dependencies": {
    "disqus-react": "^1.0.5",
    "emotion": "^9.2.6",
    "emotion-server": "^9.2.6",
    "gatsby": "^2.0.0-beta.98",
    "gatsby-plugin-catch-links": "^1.0.24",
    "gatsby-plugin-feed": "next",
    "gatsby-plugin-google-analytics": "next",
    "gatsby-plugin-offline": "next",
    "gatsby-plugin-react-helmet": "next",
    "gatsby-plugin-sharp": "next",
    "gatsby-remark-autolink-headers": "^1.4.19",
    "gatsby-remark-copy-linked-files": "next",
    "gatsby-remark-images": "next",
    "gatsby-remark-prismjs": "next",
    "gatsby-remark-responsive-iframe": "next",
    "gatsby-remark-smartypants": "next",
    "gatsby-source-filesystem": "next",
    "gatsby-transformer-remark": "next",
    "gatsby-transformer-sharp": "^2.1.1-beta.6",
    "github-slugger": "^1.2.0",
    "lodash": "^4.17.5",
    "prismjs": "^1.15.0",
    "react": "^16.3.2",
    "react-dom": "^16.3.2",
    "react-emotion": "^9.2.6",
    "react-helmet": "^5.2.0"
  },
  "devDependencies": {
    "eslint": "^4.19.1",
    "eslint-plugin-react": "^7.7.0",
    "gh-pages": "^1.2.0",
    "prettier": "^1.12.0"
  },
  "homepage": "https://loige.co",
  "keywords": [
    "gatsby",
    "blog"
  ],
  "license": "MIT",
  "main": "n/a",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/lmammino/loige.co.git"
  },
  "scripts": {
    "dev": "gatsby develop",
    "lint": "./node_modules/.bin/eslint --ext .js,.jsx --ignore-pattern public .",
    "test": "echo \"Error: no test specified\" && exit 1",
    "format": "prettier --trailing-comma es5 --no-semi --single-quote --write 'src/**/*.js' 'src/**/*.md'",
    "develop": "gatsby develop",
    "build": "gatsby build",
    "deploy": "gatsby build --prefix-paths && gh-pages -d public",
    "fix-semi": "eslint --quiet --ignore-pattern node_modules --ignore-pattern public --parser babel-eslint --no-eslintrc --rule '{\"semi\": [2, \"never\"], \"no-extra-semi\": [2]}' --fix gatsby-node.js"
  }
}

gatsby-node.js:

const _ = require('lodash')
const Promise = require('bluebird')
const path = require('path')
const getSimilarPosts = require('./getSimilarPosts')

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

  return new Promise((resolve, reject) => {
    const blogPost = path.resolve('./src/templates/blog-post.js')
    const blogIndex = path.resolve('./src/templates/blog-index.js')
    const tagIndex = path.resolve('./src/templates/tag-index.js')
    const speakingIndex = path.resolve('./src/templates/speaking-index.js')
    resolve(
      // get data for posts and tags
      graphql(
        `
        {
          allMarkdownRemark(
            sort: {fields: [frontmatter___date], order: DESC},
            filter: {frontmatter: {status: {eq: "published"}, layout: {eq: "post"}}}
          ) {
            edges {
              node {
                timeToRead
                excerpt(pruneLength: 512)
                fields {
                  slug
                }
                frontmatter {
                  date(formatString: "DD MMMM, YYYY")
                  title
                  tags
                  header_img {
                    publicURL
                  }
                }
              }
            }
          }
        }
        `
      ).then(result => {
        if (result.errors) {
          console.log(result.errors)
          reject(result.errors)
        }

        const posts = result.data.allMarkdownRemark.edges

        const perPage = 10
        const postsByTag = {}
        const postsByPage = {}
        const postsBySlug = {}

        // Create blog posts pages.
        const blogPosts = {}
        _.each(posts, (post, index) => {
          postsBySlug[post.node.fields.slug] = post

          const previous = index === posts.length - 1 ? null : posts[index + 1].node;
          const next = index === 0 ? null : posts[index - 1].node;

          // fill postsByTag
          _.each(post.node.frontmatter.tags, (tag) => {
            if (!postsByTag[tag]) {
              postsByTag[tag] = []
            }

            postsByTag[tag].push(post)
          })

          // fill postsByPage
          const currentPage = Math.floor(index / perPage) + 1
          const path = currentPage === 1 ? '/' : `/page/${currentPage}/`
          if (!postsByPage[path]) {
            postsByPage[path] = []
          }
          postsByPage[path].push(post)

          blogPosts[post.node.fields.slug] = {
            path: `/${post.node.fields.slug}/`,
            component: blogPost,
            context: {
              tags: post.node.frontmatter.tags,
              slug: post.node.fields.slug,
              previous,
              next,
            },
          }
        })

        // trigger the createPage API for every post
        _.each(Object.keys(blogPosts), (slug, index) => {
          // calculates the related posts before creating the page
          const postPage = blogPosts[slug]
          postPage.context.similar = getSimilarPosts(slug, postPage.context.tags, postsByTag, postsBySlug)
          createPage(postPage)
        })


        // Create paginated blog indexes
        const pagePaths = Object.keys(postsByPage)
        _.each(pagePaths, (path, index) => {
          const previous = index === 0 ? null : { page: index, href: pagePaths[index - 1] }
          const next = index === pagePaths.length - 1 ? null : { page: index + 2, href: pagePaths[index + 1] }

          createPage({
            path,
            component: blogIndex,
            context: {
              posts: postsByPage[path].map((p) => p.node),
              previous,
              next,
              currentPage: index + 1,
              totalPages: pagePaths.length
            },
          })
        })

        // Create blog indexes by tags
        const tags = Object.keys(postsByTag)
        _.each(tags, (tag, index) => {
          createPage({
            path: `/tag/${tag}/`,
            component: tagIndex,
            context: {
              posts: postsByTag[tag].map((p) => p.node),
              tag
            },
          })
        })

        return Promise.resolve()
      })
      .then(() => {
        // gets data for speaking
        return graphql(`
          {
            allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}, filter: {frontmatter: {status: {eq: "published"}, layout: {eq: "speaking"}}}) {
              edges {
                node {
                  fields {
                    slug
                  }
                  frontmatter {
                    date(formatString: "DD MMMM, YYYY")
                    originalDate: date
                    title
                    slug
                    event_name
                    event_link
                    event_city
                    event_location_gps
                    is_workshop
                    slides_link
                    video_link
                    with {
                      name
                      link
                    }
                  }
                }
              }
            }
          }
        `).then(result => {

          if (result.errors) {
            console.log(result.errors)
            reject(result.errors)
          }

          createPage({
            path: `/speaking/`,
            component: speakingIndex,
            context: {
              events: result.data.allMarkdownRemark.edges.map(e => e.node)
            },
          })
        })
      })
    )
  })
}

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

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

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

gatsby-browser.js: N/A
gatsby-ssr.js: N/A

needs reproduction bug

Most helpful comment

Thanks for the investigation @daon! I'll update the other starters + up the peerDependency in gatsby for those packages to the latest.

All 10 comments

I've added a Gatsby bug label, but is it possible this is an issue with @reach/router?

Very likely @brotzky. I am probably passing some parameters in a format that is unexpected by the integration layer.

Anyway, do you have any practical advice on how to explore/debug this issue more?

I have the same issue, but it only seems to appear when the gatsby-cli is using npm and not yarn. But I think it may have to do with a typo in static-entry.js

const bodyComponent = createElement(
    ServerLocation,
    { url: `${pathPrefix}${pagePath}` },
    createElement(Router,
      {
        baseuri: pathPrefix.slice(0, -1),
      },
      createElement(RouteHandler, { path: `/*` })
    )
  )

I think baseuri: should be basepath: (see: https://reach.tech/router/api/Router)

Can one of you provide a reproduction of this issue? That would help in fixing it.

@KyleAMathews, In my case I have an entire website, so there's probably to much noise. I will try to isolate the issue by starting from the gatsby blog starter and trying to add things one by one until i can identify what's the generating factor.

Meanwhile, I can confirm what @daon is saying here. A clean slate install of all the dependencies with Yarn works, which is super weird! ๐Ÿ˜จ

@KyleAMathews, here is a reproduction:

$ node -v 
v10.8.0

$ npm -v
6.2.0

$ yarn -v
Unknown command 'yarn'

$ gatsby -v
1.1.58

$ gatsby new gatsby-starter-blog-test https://github.com/gatsbyjs/gatsby-starter-blog#v2

$ cd gatsby-starter-blog-test

$ gatsby build
success open and validate gatsby-config โ€” 0.016 s
success load plugins โ€” 0.362 s
success onPreInit โ€” 0.988 s
success delete html and css files from previous builds โ€” 0.017 s
success initialize cache โ€” 0.048 s
success copy gatsby files โ€” 0.111 s
success onPreBootstrap โ€” 0.002 s
success source and transform nodes โ€” 0.181 s
success building schema โ€” 0.499 s
success createPages โ€” 0.092 s
success createPagesStatefully โ€” 0.045 s
success onPreExtractQueries โ€” 0.002 s
success update schema โ€” 0.277 s
warning Using the global `graphql` tag is deprecated, and will not be supported in v3.
Import it instead like:  import { graphql } from 'gatsby' in file:
/Users/danandersson/Projects/gatsby-test/src/templates/blog-post.js
success extract queries from components โ€” 0.094 s
success run graphql queries โ€” 0.616 s โ€” 7/7 11.40 queries/second
success write out page data โ€” 0.014 s
Generating image thumbnails [==============================] 7/7 0.1 secs 100%
success write out redirect data โ€” 0.021 s
โข€ onPostBootstrapdone generating icons for manifest
success onPostBootstrap โ€” 0.327 s

info bootstrap finished - 6.476 s

success Building production JavaScript and CSS bundles โ€” 24.291 s

error Building static HTML for pages failed

See our docs page on debugging HTML builds for help https://goo.gl/yL9lND

  581 | // Junk
  582 | var stripSlashes = function stripSlashes(str) {
> 583 |   return str.replace(/(^\/+|\/+$)/g, "");
      | ^
  584 | };
  585 |
  586 | var createRoute = function createRoute(basepath) {


  WebpackError: TypeError: Cannot read property 'replace' of undefined

  - index.js:583 stripSlashes
    [lib]/[@reach]/router/es/index.js:583:1

  - index.js:600
    [lib]/[@reach]/router/es/index.js:600:1

  - react.production.min.js:18 V
    [lib]/[react]/cjs/react.production.min.js:18:48

  - react.production.min.js:16 S
    [lib]/[react]/cjs/react.production.min.js:16:210

  - react.production.min.js:18 W
    [lib]/[react]/cjs/react.production.min.js:18:388

  - react.production.min.js:19 Object.map
    [lib]/[react]/cjs/react.production.min.js:19:67

  - index.js:211 RouterImpl.render
    [lib]/[@reach]/router/es/index.js:211:1

  - react-dom-server.node.production.min.js:28 d
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:28:207

  - react-dom-server.node.production.min.js:28 wa
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:28:493

  - react-dom-server.node.production.min.js:33 a.render
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:33:16

  - react-dom-server.node.production.min.js:32 a.read
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:32:201

  - react-dom-server.node.production.min.js:43 renderToString
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:43:1

  - static-entry.js:145 Module../.cache/static-entry.js.__webpack_exports__.default
    lib/.cache/static-entry.js:145:16


  - create-react-context.js:3 Promise._execute
    lib/.cache/create-react-context.js:3:1

@daon Is your website gatsby 2 and are you using gatsby CLI v1 (global)?

@lmammino yes, but unfortunately with CLI v2 I got the same error

$ node -v 
v10.8.0

$ npm -v
6.2.0

$ yarn -v
Unknown command 'yarn'

$ gatsby -v
2.0.0-beta.13

$ gatsby new gatsby-starter-blog-test https://github.com/gatsbyjs/gatsby-starter-blog#v2

$ cd gatsby-starter-blog-test

$ gatsby build
success open and validate gatsby-config โ€” 0.007 s
success load plugins โ€” 0.267 s
success onPreInit โ€” 1.243 s
success delete html and css files from previous builds โ€” 0.011 s
success initialize cache โ€” 0.054 s
success copy gatsby files โ€” 0.126 s
success onPreBootstrap โ€” 0.002 s
success source and transform nodes โ€” 0.124 s
success building schema โ€” 0.483 s
success createPages โ€” 0.073 s
success createPagesStatefully โ€” 0.036 s
success onPreExtractQueries โ€” 0.002 s
success update schema โ€” 0.219 s
warning Using the global `graphql` tag is deprecated, and will not be supported in v3.
Import it instead like:  import { graphql } from 'gatsby' in file:
/Users/danandersson/Projects/gatsby-starter-blog-test/src/templates/blog-post.js
success extract queries from components โ€” 0.099 s
success run graphql queries โ€” 0.548 s โ€” 7/7 12.84 queries/second
success write out page data โ€” 0.004 s
success write out redirect data โ€” 0.001 s
Generating image thumbnails [==============================] 7/7 0.2 secs 100%

info bootstrap finished - 7.136 s

โ   onPostBootstrapdone generating icons for manifest
success onPostBootstrap โ€” 0.355 s
success Building production JavaScript and CSS bundles โ€” 16.862 s

error Building static HTML for pages failed

See our docs page on debugging HTML builds for help https://goo.gl/yL9lND

  581 | // Junk
  582 | var stripSlashes = function stripSlashes(str) {
> 583 |   return str.replace(/(^\/+|\/+$)/g, "");
      | ^
  584 | };
  585 |
  586 | var createRoute = function createRoute(basepath) {


  WebpackError: TypeError: Cannot read property 'replace' of undefined

  - index.js:583 stripSlashes
    [lib]/[@reach]/router/es/index.js:583:1

  - index.js:600
    [lib]/[@reach]/router/es/index.js:600:1

  - react.production.min.js:18 V
    [lib]/[react]/cjs/react.production.min.js:18:48

  - react.production.min.js:16 S
    [lib]/[react]/cjs/react.production.min.js:16:210

  - react.production.min.js:18 W
    [lib]/[react]/cjs/react.production.min.js:18:388

  - react.production.min.js:19 Object.map
    [lib]/[react]/cjs/react.production.min.js:19:67

  - index.js:211 RouterImpl.render
    [lib]/[@reach]/router/es/index.js:211:1

  - react-dom-server.node.production.min.js:28 d
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:28:207

  - react-dom-server.node.production.min.js:28 wa
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:28:493

  - react-dom-server.node.production.min.js:33 a.render
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:33:16

  - react-dom-server.node.production.min.js:32 a.read
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:32:201

  - react-dom-server.node.production.min.js:43 renderToString
    [lib]/[react-dom]/cjs/react-dom-server.node.production.min.js:43:1

  - static-entry.js:145 Module../.cache/static-entry.js.__webpack_exports__.default
    lib/.cache/static-entry.js:145:16


  - create-react-context.js:3 Promise._execute
    lib/.cache/create-react-context.js:3:1

Think the problem has to do with the package-lock file in gatsby-starter-blog#v2

When installing using npm or when gatsby uses npm, the package-lock will only install react and react-dom v16.4.0. If I update react and react-dom to 16.4.1 or 16.4.2 the problem disappears.

When installing using yarn or when gatsby uses yarn because there is no yarn.lock file, yarn will install react and react-dom v16.4.2.

The same issue have been filed in gatsbyjs/gatsby-starter-blog#117 so maybe this issue can be closed @KyleAMathews?

Created a pull request gatsbyjs/gatsby-starter-blog#118

Thanks for the investigation @daon! I'll update the other starters + up the peerDependency in gatsby for those packages to the latest.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KyleAMathews picture KyleAMathews  ยท  97Comments

Jivings picture Jivings  ยท  112Comments

TuckerWhitehouse picture TuckerWhitehouse  ยท  69Comments

dlindahl picture dlindahl  ยท  81Comments

cusspvz picture cusspvz  ยท  128Comments