Jeremy Davis
Jeremy Davis
Sitecore, C# and web development
Jeremy Davis
Jeremy Davis
Sitecore, C# and web development

Challenges with Sitecore's GraphQL tooling

When your prototyping tools don't work the way you expect

Published 28 March 2022

I've started looking at the details of the Headless Services GraphQL endpoints in Sitecore recently. And as part of this research, I got a bit confused trying to test queries in the Sitecore UI. I've worked out what was up, but maybe others will find themselves in a similar situation, so:

When you look at at Json Rendering in the content tree, one of the fields it has is for a custom GraphQL query to help you format its data. Helpfully, that includes a built-in query prototyping tool under the "Open xGraph Browser" link:

The GraphQL field in a Json Rendering

You can use this to tweak your queries and verify that they return the data you think they do. But if you're new to using GraphQL with Sitecore, there are a some small gotchas you might hit here. When you click the link shown in the field above, you get taken to the prototyping page. The code tries to pass across your query along with some context data, but currently it doesn't work very well.

Big queries don't get passed

After a certain size, the query in your Content Editor field won't be passed. If that happens you'll get a message in the editor to warn you:

# Query was too long to transfer into editor.
# Please copy and paste your integrated mode query here to execute it.
{
}

					

As it says, if this happens you'll need to manually copy your query in.

Other context data doesn't seem to get passed either

When you click to open the prototyping page, the querystring appears to include a lot of useful data. If you decode the url, you'll get something like this:

https://cm.jsstest.localhost/sitecore/api/graph/edge/ui?query=# Editing here does not save the query on the item; copy it back when done!

query Test($contextItem: String!, $language: String!)
{
  item(path: $contextItem, language:$language) {
      id
      name
    }
}&variables={
  "datasource": "",
  "contextItem": "/sitecore/content/JssTest"
}
&sc_apikey={BDC711CC-8F6E-4B61-AF4B-27E39360CD85}

					

But in the version I'm looking at, (Sitecore v10.2, JSS v19) only the query comes across into the prototyping UI. And that means you'll see some errors while you try to get your query to run. First up, hitting "play" in the middle of the window will get you a security error if your endpoint is secured:

GraphQL playground complaining about lack of API key

It says Server cannot be reached in the query endpoint address field, and the response JSON includes the message SSC API Key is required. Pass ith 'sc_apikey' query string or HTTP header. in its data.

Now the API key it needs is probably in page querystring, but for me it wasn't passed through to the GraphQL endpoint correctly. I needed to manually move it from the page's URL into the url used for the query endpoint:

Moving the API key from the browser url to the endpoint url

But having done that I hit a second error:

{
  "errors": [
    {
      "message": "GraphQL.ExecutionError: Variable '$contextItem' is invalid. Received a null input for a non-null field. ---> GraphQL.Execution.InvalidValueException: Variable '$contextItem' is invalid. Received a null input for a non-null field.\r\n   at GraphQL.Execution.ExecutionHelper.AssertValidValue(ISchema schema, IGraphType type, Object input, String fieldName)\r\n   at GraphQL.Execution.ExecutionHelper.GetVariableValue(Document document, ISchema schema, VariableDefinition variable, Object input)\r\n   at GraphQL.Execution.ExecutionHelper.GetVariableValues(Document document, ISchema schema, VariableDefinitions variableDefinitions, Inputs inputs)\r\n   at GraphQL.DocumentExecuter.BuildExecutionContext(ISchema schema, Object root, Document document, Operation operation, Inputs inputs, Object userContext, CancellationToken cancellationToken, Metrics metrics, IEnumerable`1 listeners, Boolean throwOnUnhandledException)\r\n   at GraphQL.DocumentExecuter.<ExecuteAsync>d__8.MoveNext()\r\n   --- End of inner exception stack trace ---",
      "extensions": {
        "code": "INVALID_VALUE"
      }
    }
  ]
}

					

That's a complicated way of saying "you added a required variable called $contextItem in your query, but you've not passed a value for it". But if you look back at the data we decoded from the URL before, that variable is there. So why can't the query see it?

It took me a while to work this out, because I couldn't understand where the UI was looking for the variable. But it was right under my nose the whole time, as it turns out that the parameters for your query should be under the "query variables" pane that's hiding at the bottom left of the page:

Location of the GraphQL parameters tab

It's minimised by default, so you need to click it or drag it up to see the contents. And I found that it was empty in this case - which would explain the error. So I tried copying in the data I'd decoded from the URL:

Adding data to the GraphQL parameters

And that's a step forward - the error has changed to say that it's the "language" variable which is missing now. Which is right - that wasn't in the URL data at all. But if I add it, everything works:

A successful GraphQL query

Success!

Note: Having spoken to Sitecore Support, the failure to pass the API key and the standard parameters is confirmed as a bug. Speaking to Jeff L'Heureux at Sitecore, he pointed out that the tooling used for this GraphQL playground has been changed in a recent release - so the lack of wiring up of these parameters was probably caused by that change. If this is an issue for you, reference bug 523547 when you speak to support to raise its priority. But hopefully this will be fixed in a future release.