Skip to content

docs: add guide on graphql-http errors #2006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: source
Choose a base branch
from
5 changes: 5 additions & 0 deletions src/pages/learn/_meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@ export default {
performance: "",
security: "",
federation: "",
"-- 3": {
type: "separator",
title: "GraphQL over HTTP",
},
"debug-errors": "Common GraphQL over HTTP Errors",
}
5 changes: 5 additions & 0 deletions src/pages/learn/best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,10 @@ The articles in this section should not be taken as gospel, and in some cases ma
link: "/learn/security/",
description: "Protect GraphQL APIs from malicious operations",
},
{
title: "Common Errors",
link: "/learn/debug-errors/",
description: "Learn about common `graphql-http` errors and how to debug them.",
}
]}
/>
157 changes: 157 additions & 0 deletions src/pages/learn/debug-errors.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Common HTTP Errors and How to Debug Them

When building or consuming a GraphQL API over HTTP, it's common to run into
errors, especially during development. Understanding how to recognize and resolve these issues
can save you time and frustration.

This guide outlines common HTTP and GraphQL errors, what they mean, and how to debug them
effectively. It follows the recommendations of the
[GraphQL over HTTP spec (draft)](https://graphql.github.io/graphql-over-http/draft/),
which standardizes how GraphQL works over HTTP, including request formats, status codes,
and media types. Keep in mind that implementations may vary, so treat this as a general guide rather
than a definitive reference.

## `400 Bad Request`: Syntax or parse errors

### What it means

The server couldn't parse your request. Either the GraphQL query string is malformed,
or the JSON body isn't valid.

### Common causes

- JSON syntax errors
- Sending a plain string without wrapping it in `{ "query": "..." }`
- Using `Content-Type: application/graphql` without supporting it

### How to debug

- Validate your JSON body using a linter or formatter.
- Make sure you're sending a `POST` request with a `Content-Type: application/json` header.
- Check your GraphQL query for syntax errors. Use an IDE or linter to verify it.

## `405 Method Not Allowed`: Wrong HTTP Method

### What it means

You're using an unsupported HTTP method. Most GraphQL servers require `POST` for mutations
and may allow `GET` for queries.

### Common causes

- Sending a `PUT` or `DELETE` request instead of `POST` or `GET`
- Sending a `GET` request for a mutation, or to a server that only supports `POST` requests

### How to debug

- Check your HTTP method. Mutations must use `POST`.
- Make sure your server supports `GET` for queries.
- Refer to the [GraphQL over HTTP spec](https://graphql.github.io/graphql-over-http/draft/) to
confirm method support.

## `415 Unsupported Media Type`

### What it means

The server doesn't understand the request's `Content-Type`.

### Common causes

- Sending a GraphQL query with `Content-Type: text/plain` or another unsupported type
- Omitting the `Content-Type` header in a `POST` request

### How to debug

- Set the header explicitly: `Content-Type: application/json`.
- If you're using `application/graphql`, verify your server supports it. This content type
is optional.

## `422 Unprocessable Entity`: Missing or invalid `query`

### What it means

The server received the request, but the `query` field was missing or invalid.

### Common causes

- Sending `{}` with no `query` key
- Sending variables or an operation name without a query

### How to debug

Always include a `query` field in your request body. For example:

```json
{
"query": "{ user(id: 1) { name } }"
}
```

## `500 Internal Server Error`: Unexpected server failures

### What it means

Something went wrong on the server.

### Common causes

- An unhandled exception in a resolver
- Schema validation issues during server startup
- Missing or misconfigured middleware

### How to debug

- Check server logs or stack traces.
- Add error handling to resolvers.

## GraphQL errors with `200 OK`

### What it means

The HTTP layer succeeded, but the GraphQL operation produced errors.

### Common causes

- Querying a field that doesn't exist
- Passing incorrect arguments to a field
- Violating schema constraints, such as non-nullability
- Runtime errors during execution

### How to debug

Check the `errors` array in the response body. If the response includes a `data` property, then
your query document is likely valid and you most likely hit a runtime exception - perhaps due to
invalid input, access denial, or a bug in server logic.

If there's no `data` field, the request likely failed during validation. For example:

```json
{
"errors": [
{
"message": "Cannot query field \"foo\" on type \"Query\".",
"locations": [{ "line": 1, "column": 3 }]
}
]
}
```

Use introspection or an IDE to verify your query matches the schema.

## Understanding GraphQL response formats

Most GraphQL servers return responses using the `application/json` media type. However,
the [GraphQL over HTTP spec](https://graphql.github.io/graphql-over-http/draft/) recommends
using a more specific type: `application/graphql-response+json`.

This media type identifies the payload as a GraphQL response and helps clients
distinguish it from other types of JSON.

### What to know

- Servers may respond with `application/graphql-response+json` instead of
`application/json`.
- Clients can request this media type using the `Accept` header: `Accept: application/graphql-response+json`
- This content type is optional, but support for it is growing.
- If your client uses content negotiation, ensure your server can response with the appropriate
type or fallback to `application/json`.