How I Fixed: Gatsby GraphQL Cannot query field “query” on type “Query”.

This one had me stumped. And it may be because I’m using GraphQL wrong. But here goes:

I set up a Gatsby site, along with Postgres and Postgraphile to expose GraphQL over my database. This is frankly amazing, and achieves in about 5 minutes what would realistically take weeks to months to code myself.

So far, so good.

In order to get Gatsby to talk to Postgraphile / GraphQL, I needed this bit of config inside gatsby-config.js:

module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-graphql",
      options: {
        // Arbitrary name for the remote schema Query type
        typeName: "segments",
        // Field under which the remote schema will be accessible. You'll use this in your Gatsby query
        fieldName: "segments",
        // Url to query from
        url: "http://0.0.0.0:5000/graphql",
      },
    },
  ],
}

There’s nothing special about this, I just copy / pasted from the docs, and set my typeName and fieldName accordingly.

The typeName and fieldName are important though. And my lack of use are what caused my problem.

Inside my gatsby-node.js file I had a query like:

const result = await graphql(
`
{
segments {
findUniqueCountries {
edges {
node {
country
count
slug
}
}
}
}
}
`
)

This worked fine, and got me back the data I wanted and expected. All good.

Then I moved on, got interrupted, and came back a while later.

I crafted up a new query using the GraphiQL GUI, and had a working result set. All good. Let’s copy / paste that right into the code and carry on, right?

For simplicity, let’s just re-use the query above, but inside GraphiQL:

query MyQuery {
  findUniqueCountries {
    edges {
      node {
        country
        count
        slug
      }
    }
  }
}

That works.

But if you copy / paste it into your code:

 ERROR #85923  GRAPHQL

There was an error in your GraphQL query:

Cannot query field "findUniqueCountries" on type "query".

If you don't expect "findUniqueCountries" to exist on the type "query" it is most likely a typo.
However, if you expect "findUniqueCountries" to exist there are a couple of solutions to common problems:

- If you added a new data source and/or changed something inside gatsby-node.js/gatsby-config.js, please try a restart of your development server
- The field might be accessible in another subfield, please try your query in GraphiQL and use the GraphiQL explorer to see which fields you can query and what shape they have
- You want to optionally use your field "findUniqueCountries" and right now it is not used anywhere. Therefore Gatsby can't infer the type and add it to the GraphQL schema. A quick fix is to add a least one entry with that field ("dummy content")

It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned "dummy content". Visit our docs to learn how you can define the schema for "query":
https://www.gatsbyjs.org/docs/schema-customization/#creating-type-definitions

File: gatsby-node.js:108:24

This confused me no end.

Well, there may be different reasons for why this happens, but in my case it was because in copy / pasting, I was no longer wrapping in the segments type name like in my original working example. Whoops.

Worth a check at your end all the same, as it may be the cause of your problems, too.

Edit: The reason for my confusion, in part, stems from having two GraphiQL instances running. I had one available on port 5000, provided by postgraphile, and another on Gatsby’s default port. If using the GraphiQL provided by Gatsby, there is an extra nested layer (for segments in my case), which does make it easy to copy / paste the query out from the GUI.

No Time For a REST

Phew, it’s been another red hot, football-filled week here in the UK. I’m sure for some of you, 29°C is positively chilly. But for me, it’s been baking. Not helped by an evil selection of naughty wasps making camp outside my window, forcing me to work without fresh air. Lovely.

Anyway, I’m sure you don’t tune in for weather updates, or for my views on the Sports Ball. Let’s get back to the good stuff.

Do You GraphQL?

One of the most interesting bits of tech about at the moment, in my opinion, is GraphQL.

GraphQL, briefly, is an alternative to REST. The main difference between ‘REST’ and GraphQL being that we – as consumers – can specify exactly which bits of data we want / need, and the server returns just the things we care about, and nothing more.

Also, you only need one endpoint with GraphQL, as often opposed to many with ‘REST’.

Now, I put REST in inverted commas as the typical RESTful API’s that I both create, and work with, are not truly RESTful. Pragmatism, and all that. That’s why I’ve more typically started referring to these types of API’s as JSON APIs.

But I digress.

Like every new piece of tech, there are often a bunch of advocates shouting loudly, particularly on sites like Twitter, about how if you’re not using GraphQL then you’re basically a dinosaur.

how-to-graphqlThen recently – I think maybe a few weeks ago – I came across a really interesting website about GraphQL. It’s called How To GraphQL.

Why I like the site is that there are some generic introduction tutorials, and then some more language specific tutorials. There’s React for the front end, along with Node and Elixir on the back end. No PHP, mind. More on that in a second. I chose the Elixir tutorial, and enjoyed playing around with it.

After playing around with the Elixir back end implementation I’d created, I wondered how this might translate into PHP. I was already aware that the API Platform can support GraphQL so used that as a starting point. I kept my implementation identical (well, as close as) to the setup in the How To GraphQL Elixir tutorial. The idea being that I could switch out the two, and the front end shouldn’t care.

It turned out to be a really interesting exercise. I’d be happy to share my code if anyone has any interest? There’s nothing fancy there, but it was a fun learning experience for me.

What I did find most interesting was in that Dunglas, the creator of the API Platform (and many other cool things – very clever guy, well worth following), isn’t quite the GraphQL advocate I expected. These two tweet threads are interesting reading:

and:

I’d be really interested to hear about your experiences with GraphQL.

Video Update

This week saw three new videos added to the site:

GET’ting Multiple Resources [API Platform]

I mentioned last week that in many ways I’ve been doing the API Platform a disservice.

In taking as many videos as I have to show a single end point API I may have made things look more difficult than they really are.

We’ve used this setup as an excuse to cover some interesting, and useful / commonly needed things such as customisation of your route paths, and defining custom operations (the Health check).

If you don’t need to customise anything, getting an API up and running using the API Platform is really remarkably rapid.

All that said, I stand by this approach. We’ve played around with some cool features. This is all stuff that will help you in the real world.

PUT to Update Existing Data [API Platform]

The API Platform takes an interesting approach to the process of updating existing data.

There’s no implementation of PATCH , the most controversial / complex HTTP Verb. And that’s fine. Less controversy is always a good thing, imo. Besides which, the more I work with the front end, the less I find any use for PATCH  anyway. Typically I will have the full resource, so making full updates to that resource is easy enough.

We cover a little potential gotcha in the way that API Platform differs from the Symfony 4 JSON API, and Symfony 4 with FOSRESTBundle approaches. This is in the status code returned by the API Platform, and why they may choose to do this.

DELETE to Remove Data [API Platform]

Adding an implementation for DELETE  is probably the easiest of the whole lot. This is partly because we’ve done all the hard work already. But also because deleting stuff just works. There’s very little to it.

Now, in the real world you’d probably want to restrict who can and can’t delete, and things get a little more complex. But the underlying operation itself is very straightforward.

There’s just one thing left to do with our API Platform setup, and that’s handle the error paths. We’ll get on to that in the final video in this part of the series.

Live Stream Update

I’ve recorded the first “live stream”. It’s on my laptop, waiting for a touch of editing. I need to mask a few bits of config due to security reasons.

I also hit on a proper issue. The domain I was planning to launch under has expired. And worse, because I let it expire and didn’t renew it, it’s gone into grace period. And now Namecheap want $108 to reactivate it. Silly me.

Ok, so this may delay the launch of the thing in the real world. It’s not going to stop me writing the code. I wanted to get this video out this week. It will slip into next week. Fortunately (depending on how you look at it), I have a couple of long train journeys on Monday and Tuesday evening next week. The perfect time to edit videos – even if it does draw a few funny looks.

As a reminder, the live stream stuff will not be getting a write up. These will be video only, but you’re more than welcome to raise questions, or ask to see more detail etc. I’ll share all that via the forum.

Ok, that about wraps it up from me this. As ever, have a great weekend, and happy coding.

Chris