title: GraphQL Error: Field "image" must not have a selection since type "String" has no subfields
body: <p><strong>Description</strong></p>
  
  <p>I am new and learning GatsbyJs/NetlifyCM/GraphQL so I am sorry if I come across as stupid.  I, however, have been trying to fix this issue for 5 days now and am at my wits end.  I am trying to implement NetlifyCMS into a GatsbyJS blog starter.  I seem to have everything working except the images.  Graphql is querying the image URL as "img/image.jpg" which is what is set in the MD file, and that works fine. However, when I make a new post with NetlifyCMS it sets the URL to "/img/image.jpg" and graphql can't seem to find it.  The extra slash in front causes the error.  If I remove the slash OR put a dot in front of the slash, "./img/image.jpg" it builds fine which leads me to believe relative paths may be working?  I have read <a href="https://github.com/gatsbyjs/gatsby/issues/4123" rel="nofollow noreferrer">issue 4123</a>, <a href="https://github.com/gatsbyjs/gatsby/issues/13938" rel="nofollow noreferrer">issue 13938</a>, <a href="https://github.com/gatsbyjs/gatsby/issues/5990" rel="nofollow noreferrer">issue 5990</a>, As well as multiple other similar issues and blogs and still, am unable to get it to work.  I have tried implementing <strong>gatsby-remark-relative-images</strong> and <strong>gatsby-plugin-netlify-cms</strong> but neither seems to fix it.</p>
  
  <p>Any help would be appreciated.  I am newer at web development and very new to gatsby/graphql.  Thank you.</p>
  
  <p><strong>Steps to reproduce</strong></p>
  
  <p>remove or add a / in front of the image URL in the MD file.  Here is a link to the repo to clone/download <a href="https://github.com/AaronCuddeback/blog.aaroncuddeback.com" rel="nofollow noreferrer">https://github.com/AaronCuddeback/blog.aaroncuddeback.com</a></p>
  
  <p><strong>Environment</strong></p>
  
  <pre><code>System:
      OS: Windows 10
      CPU: (16) x64 Intel(R) Core(TM) i9-9900KF CPU @ 3.60GHz
    Binaries:
      Node: 12.13.0 - C:\Program Files\nodejs\node.EXE
      npm: 6.13.0 - ~\AppData\Roaming\npm\npm.CMD
    Languages:
      Python: 2.7.17 - /usr/bin/python
    Browsers:
      Edge: 44.18362.387.0
    npmPackages:
      gatsby: 2.18.2 =&gt; 2.18.2 
      gatsby-image: 2.2.33 =&gt; 2.2.33 
      gatsby-plugin-canonical-urls: 2.1.15 =&gt; 2.1.15 
      gatsby-plugin-emotion: 4.1.15 =&gt; 4.1.15 
      gatsby-plugin-feed: 2.3.21 =&gt; 2.3.21 
      gatsby-plugin-google-analytics: 2.1.28 =&gt; 2.1.28 
      gatsby-plugin-netlify: ^2.1.25 =&gt; 2.1.25 
      gatsby-plugin-netlify-cms: ^4.1.28 =&gt; 4.1.28 
      gatsby-plugin-netlify-cms-paths: ^1.3.0 =&gt; 1.3.0 
      gatsby-plugin-postcss: 2.1.15 =&gt; 2.1.15 
      gatsby-plugin-react-helmet: 3.1.15 =&gt; 3.1.15 
      gatsby-plugin-sharp: 2.3.2 =&gt; 2.3.2 
      gatsby-plugin-sitemap: 2.2.21 =&gt; 2.2.21 
      gatsby-plugin-typescript: 2.1.19 =&gt; 2.1.19 
      gatsby-remark-abbr: 2.0.0 =&gt; 2.0.0 
      gatsby-remark-copy-linked-files: 2.1.30 =&gt; 2.1.30 
      gatsby-remark-images: 3.1.33 =&gt; 3.1.33 
      gatsby-remark-prismjs: 3.3.24 =&gt; 3.3.24 
      gatsby-remark-relative-images: ^0.2.3 =&gt; 0.2.3 
      gatsby-remark-responsive-iframe: 2.2.27 =&gt; 2.2.27 
      gatsby-remark-smartypants: 2.1.16 =&gt; 2.1.16 
      gatsby-source-filesystem: 2.1.38 =&gt; 2.1.38 
      gatsby-transformer-json: 2.2.19 =&gt; 2.2.19 
      gatsby-transformer-remark: 2.6.37 =&gt; 2.6.37 
      gatsby-transformer-sharp: 2.3.5 =&gt; 2.3.5 
      gatsby-transformer-yaml: 2.2.17 =&gt; 2.2.17 
  </code></pre>
  
  <p><strong>File Contents:</strong></p>
  
  <p>gatsby-config.js:</p>
  
  <pre><code>const path = require('path');
  
  module.exports = {
    siteMetadata: {
      title: 'Ghost',
      description: 'The professional publishing platform',
      siteUrl: 'https://gatsby-casper.netlify.com', // full path to blog - no ending slash
    },
    mapping: {
      'MarkdownRemark.frontmatter.author': 'AuthorYaml',
    },
    plugins: [
      {
        resolve: 'gatsby-source-filesystem',
        options: {
          path: `${__dirname}/static/img`,
          name: 'uploads',
        },
      },
      {
        resolve: 'gatsby-source-filesystem',
        options: {
          path: `${__dirname}/src/content`,
          name: 'content',
        },
      },
      {
        resolve: `gatsby-plugin-netlify-cms-paths`,
        options: {
          cmsConfig: `/static/admin/config.yml`,
        },
      },
      'gatsby-plugin-sitemap',
      'gatsby-plugin-sharp',
      {
        resolve: 'gatsby-transformer-remark',
        options: {
          plugins: [
            `gatsby-plugin-netlify-cms-paths`,
            {
              resolve: `gatsby-remark-relative-images`,
              options: {
                name: 'uploads', // Must match the source name ^
              },
            },
            {
              resolve: 'gatsby-remark-images',
              options: {
                maxWidth: 1170,
                quality: 90,
              },
            },
            {
              resolve: 'gatsby-remark-responsive-iframe',
              options: {
                wrapperStyle: 'margin-bottom: 1rem',
              },
            },
            'gatsby-remark-prismjs',
            'gatsby-remark-copy-linked-files',
            'gatsby-remark-smartypants',
            'gatsby-remark-abbr',
          ],
        },
      },
      'gatsby-transformer-json',
      {
        resolve: 'gatsby-plugin-canonical-urls',
        options: {
          siteUrl: 'https://gatsby-casper.netlify.com',
        },
      },
      'gatsby-plugin-emotion',
      'gatsby-plugin-typescript',
      'gatsby-transformer-sharp',
      'gatsby-plugin-react-helmet',
      'gatsby-transformer-yaml',
      'gatsby-plugin-feed',
      {
        resolve: 'gatsby-plugin-postcss',
        options: {
          postCssPlugins: [require('postcss-color-function'), require('cssnano')()],
        },
      },
      {
        resolve: `gatsby-plugin-google-analytics`,
        options: {
          trackingId: 'UA-XXXX-Y',
          // Puts tracking script in the head instead of the body
          head: true,
          // IP anonymization for GDPR compliance
          anonymize: true,
          // Disable analytics for users with `Do Not Track` enabled
          respectDNT: true,
          // Avoids sending pageview hits from custom paths
          exclude: ['/preview/**'],
          // Specifies what percentage of users should be tracked
          sampleRate: 100,
          // Determines how often site speed tracking beacons will be sent
          siteSpeedSampleRate: 10,
        },
      },
      `gatsby-plugin-netlify-cms`,
      `gatsby-plugin-netlify`,
    ],
  };
  </code></pre>
  
  <p>gatsby-node.js</p>
  
  <pre><code>const path = require('path');
  const _ = require('lodash');
  const { fmImagesToRelative } = require('gatsby-remark-relative-images');
  
  exports.onCreateNode = ({ node, actions, getNode }) =&gt; {
    const { createNodeField } = actions;
    fmImagesToRelative(node);
  
    // Sometimes, optional fields tend to get not picked up by the GraphQL
    // interpreter if not a single content uses it. Therefore, we're putting them
    // through `createNodeField` so that the fields still exist and GraphQL won't
    // trip up. An empty string is still required in replacement to `null`.
    switch (node.internal.type) {
      case 'MarkdownRemark': {
        const { permalink, layout, primaryTag } = node.frontmatter;
        const { relativePath } = getNode(node.parent);
  
        let slug = permalink;
  
        if (!slug) {
          slug = `/${relativePath.replace('.md', '')}/`;
        }
  
        // Used to generate URL to view this content.
        createNodeField({
          node,
          name: 'slug',
          value: slug || '',
        });
  
        // Used to determine a page layout.
        createNodeField({
          node,
          name: 'layout',
          value: layout || '',
        });
  
        createNodeField({
          node,
          name: 'primaryTag',
          value: primaryTag || '',
        });
      }
    }
  };
  
  exports.createPages = async ({ graphql, actions }) =&gt; {
    const { createPage } = actions;
  
    const result = await graphql(`
      {
        allMarkdownRemark(
          limit: 2000
          sort: { fields: [frontmatter___date], order: ASC }
          filter: { frontmatter: { draft: { ne: true } } }
        ) {
          edges {
            node {
              excerpt
              timeToRead
              frontmatter {
                title
                tags
                date
                draft
                image {
                  childImageSharp {
                    fluid(maxWidth: 3720) {
                      aspectRatio
                      base64
                      sizes
                      src
                      srcSet
                    }
                  }
                  publicURL
                }
                author {
                  id
                  bio
                  avatar {
                    children {
                      ... on ImageSharp {
                        fixed(quality: 90) {
                          src
                        }
                      }
                    }
                  }
                }
              }
              fields {
                layout
                slug
              }
            }
          }
        }
        allAuthorYaml {
          edges {
            node {
              id
            }
          }
        }
      }
    `);
  
    if (result.errors) {
      console.error(result.errors);
      throw new Error(result.errors);
    }
  
    // Create post pages
    const posts = result.data.allMarkdownRemark.edges;
  
    // Create paginated index
    const postsPerPage = 6;
    const numPages = Math.ceil(posts.length / postsPerPage);
  
    Array.from({ length: numPages }).forEach((_, i) =&gt; {
      createPage({
        path: i === 0 ? '/' : `/${i + 1}`,
        component: path.resolve('./src/templates/index.tsx'),
        context: {
          limit: postsPerPage,
          skip: i * postsPerPage,
          numPages,
          currentPage: i + 1,
        },
      });
    });
  
    posts.forEach(({ node }, index) =&gt; {
      const { slug, layout } = node.fields;
      const prev = index === 0 ? null : posts[index - 1].node;
      const next = index === posts.length - 1 ? null : posts[index + 1].node;
  
      createPage({
        path: slug,
        // This will automatically resolve the template to a corresponding
        // `layout` frontmatter in the Markdown.
        //
        // Feel free to set any `layout` as you'd like in the frontmatter, as
        // long as the corresponding template file exists in src/templates.
        // If no template is set, it will fall back to the default `post`
        // template.
        //
        // Note that the template has to exist first, or else the build will fail.
        component: path.resolve(`./src/templates/${layout || 'post'}.tsx`),
        context: {
          // Data passed to context is available in page queries as GraphQL variables.
          slug,
          prev,
          next,
          primaryTag: node.frontmatter.tags ? node.frontmatter.tags[0] : '',
        },
      });
    });
  
    // Create tag pages
    const tagTemplate = path.resolve('./src/templates/tags.tsx');
    const tags = _.uniq(
      _.flatten(
        result.data.allMarkdownRemark.edges.map(edge =&gt; {
          return _.castArray(_.get(edge, 'node.frontmatter.tags', []));
        }),
      ),
    );
    tags.forEach(tag =&gt; {
      createPage({
        path: `/tags/${_.kebabCase(tag)}/`,
        component: tagTemplate,
        context: {
          tag,
        },
      });
    });
  
    // Create author pages
    const authorTemplate = path.resolve('./src/templates/author.tsx');
    result.data.allAuthorYaml.edges.forEach(edge =&gt; {
      createPage({
        path: `/author/${_.kebabCase(edge.node.id)}/`,
        component: authorTemplate,
        context: {
          author: edge.node.id,
        },
      });
    });
  };
  
  exports.onCreateWebpackConfig = ({ stage, actions }) =&gt; {
    // adds sourcemaps for tsx in dev mode
    if (stage === `develop` || stage === `develop-html`) {
      actions.setWebpackConfig({
        devtool: 'eval-source-map',
      });
    }
  };
  </code></pre>