graphql-over-http: What is the rationale for handling Invalid parameters as 400?

It feels quite unintuitive to me and my team that Invalid parameters is a 400 whereas most other ‘bad requests’ e.g. Document parsing failure are 200s.

The server SHOULD use the 200 status code for every response to a well-formed GraphQL-over-HTTP request

From digging through the spec I can see

Note: An HTTP request that encodes parameters of the same names but of the wrong type, or that omits required parameters, is not a well-formed GraphQL-over-HTTP request.

So I guess my question is equivalent to asking why this is not considered well-formed when so many other varieties of ‘bad request’ are? The GraphQL spec doesn’t really make any distinction along these lines; it’s just a single concept of valid vs invalid

About this issue

  • Original URL
  • State: closed
  • Created 5 months ago
  • Comments: 15 (9 by maintainers)

Most upvoted comments

Thanks for the clarification

Absolutely; please feel free to submit a PR! If you hover over the spec text a little GitHub icon should appear; click that to go to the file in question (and, in fact, the lines) and then click the edit pen icon at the top right to start making changes - GitHub should guide you through the process from there.

Note that “a well-formed request” is defined here: https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#request-parameters

In the first example:

  • ✔️ It has query and it is a string
  • ✔️ operationName is missing, but optional
  • ✔️ variables is missing, but optional
  • ✔️ extensions is missing, but optional

The second sample is similar except:

  • ✔️ variables is present, and is a map

Whereas if we compare to the previous example with qeury:

  • query is missing

And the previous example with variables being an array:

  • variables is present, but not a map

Both of these are “well-formed requests”, noting that the first has an unknown property that is ignored during deserialization.

{ 
  "query": "query($codes: [String!]) { systems (where: {code_IN: $codes}) { code }	}",
  "codes": [ null ]
}
{ 
  "query": "query($codes: [String!]) { systems (where: {code_IN: $codes}) { code }	}",
  "variables" : { "codes": [ null ] }
}

As these are well-formed requests, these errors occur during validation according to the main GraphQL spec. The current GraphQL-over-HTTP draft spec indicates that for application/json responses to well-formed requests [which attempt to be executed] it should return 200 so it is known that the response is a GraphQL response.

doesn’t look like a GraphQL request at all

I don’t think this is true. The invalidity of the parameters can only be deduced by first parsing a valid GraphQL query document, so the request does at least partially look like a GraphQL request.

I think it will depend on the language in use. For GraphQL.NET, attempting to deserialize a request with an array for variables will throw an exception within the deserializer. So essentially, it might as well be garbage text; it can’t proceed any further. If it tried to deserialize a request with qeury instead of query, it wouldn’t crash the deserializer, but would skip the property, so query would be null. It would also be a request that could not be executed since there is no document to execute. Either way, the error would occur within the GraphQL-over-HTTP layer, before reaching the GraphQL engine, and so it would return a 400 error since it could not attempt to execute the request, regardless of anything inside the GraphQL spec.

However, an implementation in Node or another language might behave differently.