gatsby: Cannot read property 'childImageSharp' of null

I’ve been playing with Gatsby trying to create a website that pulls data from a json file and generates pages. On each page a list of links/cards is displayed. Everything worked fine until I added images and tried using the sharp plugin (gatsby-plugin-sharp and gatsby-transformer-sharp)

If I remove from the card.js file, image from the Card_details fragment, const { small } = image.childImageSharp, and the img tag, it all works as expected except no image.

This error in GraphiQL

{
  "errors": [
    {
      "message": "Path must be a string. Received undefined",
      "locations": [
        {
          "line": 9,
          "column": 7
        }
      ],
      "path": [
        "linksJson",
        "links",
        0,
        "image"
      ]
    }
  ],
  "data": {
    "linksJson": {
      "page": "/page1",
      "title": "Page 1",
      "links": [
        {
          "title": "Card 1",
          "url": "https://www.gatsbyjs.org/tutorial/",
          "description": "Card 1 description.",
          "image": null
        }
      ]
    }
  }
}

and this in the chrome console

card.js:19 Uncaught TypeError: Cannot read property ‘childImageSharp’ of null at Card.render (card.js:19) at Card.render (createPrototypeProxy.js:44) at ReactCompositeComponent.js:793 at measureLifeCyclePerf (ReactCompositeComponent.js:73) at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:792) at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:819) at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:359) at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:255) at Object.mountComponent (ReactReconciler.js:43) at ReactDOMComponent.mountChildren (ReactMultiChild.js:234)

Am I missing something or doing something wrong? The index page generates correctly and displays a list of pages, when I click to one of the pages, that is when it doesn’t work. Thanks for any help.

Here is the code I use.

links.json

[
  {
    "page": "/page1",
    "title": "Page 1",
    "links": [
      {
        "title": "Card 1",
        "url": "https://www.gatsbyjs.org/tutorial/",
        "description": "Card 1 description.",
        "image": "images/2015-03-02-11.30.09.jpg"
      }
    ]
  },
  {
    "page": "/page2",
    "title": "Page 2",
    "links": [
      {
        "title": "Card 1",
        "url": "https://www.gatsbyjs.org/tutorial/",
        "description": "Card 1 description.",
        "image": "images/2015-06-20-11.09.16.jpg"
      },
      {
        "title": "Card 2",
        "url": "https://www.gatsbyjs.org/tutorial/",
        "description": "Card 2 description.",
        "image": "images/2015-12-07-20.31.40.jpg"
      }
    ]
  }
]

page.js template

import React from 'react';
import Helmet from 'react-helmet';
import Card from "../components/card"

export default function Template({data}) {
  const {linksJson: pages} = data;
  return (
    <div>
    <h2>{pages.title}</h2>
    <ul>
    {pages.links.map((node, key) => (
    <li key={key}>
    <Card
    
    card={node}
    />
</li>
    ))}
    </ul>
    </div>
  )
};

export const pageQuery = graphql`
  query PageByPath($path: String!) {
    linksJson (page: {eq :$path}) {
      page
      title
      ...Card_details
    }
  }
`

card.js component

import * as PropTypes from "prop-types"
import React from "react"
import Link from "gatsby-link"
import styles from '../layouts/card.module.scss';

class Card extends React.Component {
  static propTypes = {
    card: PropTypes.shape({
      title: PropTypes.string.isRequired,
      url: PropTypes.string.isRequired,
      description: PropTypes.string.isRequired,
      image: PropTypes.object,
    }).isRequired,
  }
  constructor() {
    super()
  }

  render() {
    const { title, url, description, image } = this.props.card
    const { small } = image.childImageSharp

    return (
      <a
        href={url}
        className={styles.card}
      >
 
        <img
          src={small.src}
          srcSet={small.srcSet}
          sizes="(min-width: 960px) 292px, 33vw" 
          className={styles.image} 
          alt="" 
        />

        <div className={styles.content}>
          <h2 className={styles.title}>
            {title}
          </h2>
          <p className={styles.description}>
            {description}
          </p>
        </div>

      </a>
    )
  }
}

export default Card

export const CardFragment = graphql`
  fragment Card_details on LinksJson {
    links {
      title
      url
      description
      image {
        childImageSharp {
          small: responsiveSizes(maxWidth: 292, maxHeight: 292) {
            src
            srcSet
          }
        }
      }
    }
  }
`

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 10
  • Comments: 31 (7 by maintainers)

Commits related to this issue

Most upvoted comments

@cryptoverted Did you try deleting the .cache and public folder and then running the dev server again?

A note for everyone coming to this thread by googling. After gatsby new, you might have in your gatsby-config.js something similar like this:

    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },

After you start implementing blog posts like in the tutorial, you might add or change the code following:

    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },

Now, you might have something like this:

  const data = useStaticQuery(graphql`
    query {
      headerImage: file(relativePath: { eq: "header.jpg" }) { // <--- here
        childImageSharp {
          fluid(maxWidth: 1200) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

Then you have error Cannot read property 'childImageSharp' of null. The reason is that the relative path has changed. It’s now images/header.jpg.

@cryptoverted Did you try deleting the .cache and public folder and then running the dev server again?

Thanks to you solved my problem. It was caused by cache.

Just a note for future readers: I had this problem after renaming a directory of a blog post. Running gatsby clean worked for me straight away.

A note for everyone coming to this thread by googling. After gatsby new, you might have in your gatsby-config.js something similar like this:

    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },

After you start implementing blog posts like in the tutorial, you might add or change the code following:

    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      },
    },

Now, you might have something like this:

  const data = useStaticQuery(graphql`
    query {
      headerImage: file(relativePath: { eq: "header.jpg" }) { // <--- here
        childImageSharp {
          fluid(maxWidth: 1200) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

Then you have error Cannot read property 'childImageSharp' of null. The reason is that the relative path has changed. It’s now images/header.jpg.

This fixed the issue for me, many thanks!

For some reason, when you do the first gatsby build it will break at childImageSharp, but if you run again gatsby build it will work perfectly.

You can do a double gatsby build and it will works fine.

@cryptoverted have you tried one of example sites that use gatsby-transformer-sharp? image-processing + using-gatsby-image are great examples of how to do things.