Austinmdem
Austinmdem

Reputation: 109

Field "image" must not have a selection since type "String" has no subfields. - What am I missing?

Like many, all I want to do is to be able to use a simple gastby blog with NetlifyCMS. For one second I was able to get an image appear but never again after that. I've tried countless solutions from other posts and I'm just getting nowhere. Going on 3 days now.

I'm getting the common:

Field "image" must not have a selection since type "String" has no subfields

Can someone take a look and my code and see if theres something I'm missing?

config.yml

backend:
  name: github
  branch: development
  repo: removedforworkreasons

media_folder: static/img
public_folder: /img

collections:
  - name: blog
    label: Blog
    folder: src/posts
    create: true
    fields:
      - { name: path, label: Path }
      - { name: date, label: Date, widget: date }
      - { name: title, label: Title }
      - { name: description, label: Description }
      - { name: image, label: Image, widget: image }
      - { name: body, label: Body, widget: markdown }

gatsby-config.js

module.exports = {
  siteMetadata: {
    title: `removedforwork`,
    description: `removedforwork`,
    author: `removed`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-sass`,
    `gatsby-plugin-remove-serviceworker`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `img`,
        path: `${__dirname}/static/img`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/posts`,
      },
    },
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-relative-images`,
            options: {
              // [Optional] The root of "media_folder" in your config.yml
              // Defaults to "static"
              staticFolderName: "static",
            },
          },
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 590,
            },
          },
        ],
      },
    },
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
      },
    },
    {
      resolve: "gatsby-plugin-react-svg",
      options: {
        rule: {
          include: /assets/,
        },
      },
    },
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
    `gatsby-plugin-netlify-cms`,
    `gatsby-plugin-netlify`,
  ],
}

gatsby-node.js (might as well throw it in)

const path = require('path')

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

    if (node.internal.type === "MarkdownRemark") {
        const slug = path.basename(node.fileAbsolutePath, '.md')

        createNodeField({
            node,
            name: 'slug',
            value: slug
        })
    }
}

module.exports.createPages = async ({ graphql, actions}) => {
    const { createPage } = actions
    const blogTemplate = path.resolve('./src/templates/blog.js')
    const res = await graphql(`
        query {
            allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
        }
    `)

    res.data.allMarkdownRemark.edges.forEach((edge) => {
        createPage({
            component: blogTemplate,
            path: `/blog/${edge.node.fields.slug}`,
            context: {
                slug: edge.node.fields.slug
            }
        })
    })
}

Page that displays all blog posts (Not a template) pages/blog.js

import React from "react"
import { Link, graphql, useStaticQuery } from "gatsby"

import Layout from "../components/layout/layout"

import Img from 'gatsby-image'

const Blog = () => {
  const data = useStaticQuery(graphql`
    query {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              title
              date
              image {
                childImageSharp {
                  fluid {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
            }
            fields {
              slug
            }
          }
        }
      }
    }
  `)

  return (
    <>
      <Layout>
        <main className="main">
          <div className="articles">
            <h1 className="articles__title">Articles</h1>
            <section className="articles__list">
              {data.allMarkdownRemark.edges.map(edge => {
                return (
                  <a className="articles__article">
                    <div className="articles__article-artwork">
                      <figure className="articles__article-artwork-wrapper">
                        <Img fluid={edge.node.frontmatter.image.childImageSharp.fluid} />
                      </figure>
                    </div>
                    <h2 className="articles__article-title">
                      <Link to={`/blog/${edge.node.fields.slug}`}>
                        {edge.node.frontmatter.title}
                      </Link>
                    </h2>
                    <Link>
                      <p>{edge.node.frontmatter.date}</p>
                    </Link>
                    <div className="articles__article-description">
                      <p></p>
                    </div>
                    <span className="articles__article-more">Read more...</span>
                  </a>
                )
              })}
            </section>
          </div>
        </main>
      </Layout>
    </>
  )
}
export default Blog

templates/blog.js

import React from "react"
import { graphql } from "gatsby"

import Layout from "../components/layout/layout"

import Img from 'gatsby-image'

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      frontmatter {
        title
        date
        image {
          childImageSharp {
            fluid {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
      html
    }
  }
`

const Blog = props => {
  return (
    <Layout>
      <main className="main">
        <div className="article-page">
          <header className="article-page__header">
            <div className="article-page__header-inner">
              <h1 className="article-page__title">
                {props.data.markdownRemark.frontmatter.title}
              </h1>
            </div>
          </header>
         <Img fluid={props.data.markdownRemark.frontmatter.image.childImageSharp.fluid} />
          <p>{props.data.markdownRemark.frontmatter.date}</p>
          <section className="article-page">
            <div className="articles-page__inner">
              <div
                className="article-page__content"
                dangerouslySetInnerHTML={{
                  __html: props.data.markdownRemark.html,
                }}
              ></div>
            </div>
          </section>
        </div>
      </main>
    </Layout>
  )
}

export default Blog

This has been brutal for me. I think I just need another pair of eyes to maybe point out something dumb I did, but seems like a common issues with gatsby and netlifycms.

Thanks in advance!!!

Upvotes: 4

Views: 3835

Answers (3)

Ferran Buireu
Ferran Buireu

Reputation: 29320

There are multiple sources for this error:

  • Check the spelling of the images: if you are querying for an abc.jpg and your image is named def.jpg Gatsby will resolve the missing image field as a string by default. It will happen the same for missing images, as well as for wrong paths or format images types (jpg, png, etc).

  • Check plugin's order, specially for those related to the filesystem or transformers and sharps.

  • If your image is not a sibling, or in other words, is in the same folder as the JSON file, the appropriate plugins will resolve them to strings, as it does not actually "knows" where the file is located.

    Otherwise, it will resolve the files to a file node. You can confirm this by issuing gatsby develop, open http://localhost:8000/___graphql, and on the right side, on the docs, go through the hierarchy of nodes. You'll see that is actually a string, but if you move the images to the same folder and make the necessary adjustments, issue gatsby clean to purge all cached items and reissue gatsby develop and open a new window to http://localhost:8000/___graphql, you'll see that the now the item is actually a file node.

Resources:

Upvotes: 3

Anastasis
Anastasis

Reputation: 729

In Gatsby-config, the order of plugins does matter here:

I solved it by including gatsby-transformer-sharp gatsby-plugin-sharp and 'gatsby-transformer-remark' before the gatsby-source-filesystem

'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
{
  resolve: 'gatsby-transformer-remark',
  options: {
    plugins: [
      {
        resolve: 'gatsby-remark-relative-images-v2',
        options: {
          name: 'uploads',
        },
      },
      {
        resolve: 'gatsby-remark-images',
        options: {
          // It's important to specify the maxWidth (in pixels) of
          // the content container as this plugin uses this as the
          // base for generating different widths of each image.
          maxWidth: 2048,
        },
      },
      {
        resolve: 'gatsby-remark-copy-linked-files',
        options: {
          destinationDir: 'static',
        },
      },
    ],
  },
},
{
  // keep as first gatsby-source-filesystem plugin for gatsby image support
  resolve: 'gatsby-source-filesystem',
  options: {
    path: `${__dirname}/static/assets`,
    name: 'uploads',
  },
},

Upvotes: 1

jlblca9l_kpblca
jlblca9l_kpblca

Reputation: 504

For anyone looking for a solution, downgrading gatsby-remark-relative-images to version 0.3.0 worked for me:

npm i [email protected]

Don't forget to add a call to fmImagesToRelative in onCreateNode in gatsby-node.js:

const {fmImagesToRelative} = require("gatsby-remark-relative-images");

// ...

exports.onCreateNode = ({node, actions, getNode}) => {
    fmImagesToRelative(node); // <- this
    // ...
};

Upvotes: 2

Related Questions