· 3 min read

2025 is the year of GraphQL error handling!

Lots of exciting things are happening in the GraphQL space this year!

Lots of exciting things are happening in the GraphQL space this year!

Happy new year everyone! 🎉

You may not have noticed it yet, but something big has happened on January 1st 2025…

GraphQL servers are now required to support the application/graphql-response+json content type 🎉! (PS: At least according to the current GraphQL over HTTP draft)

From 1st January 2025 (2025-01-01T00:00:00Z), a server MUST support any GraphQL-over-HTTP request which accepts the application/graphql-response+json media type (as indicated by the Accept header) using the UTF-8 encoding.

Doesn’t sound like a big deal? Well, it might not be a huge deal right now because the spec itself is a draft, and it will take time for the ecosystem to adapt, but it’s paving the way for a much better error handling story.

Let’s dive in.

What problem are we fixing?

In 2024 and the years before, the traditional Content-Type for GraphQL response was application/json:

// 200 OK
// Content-Type: application/json
{
  "data": {
    "user": {
      "name": "Luke Skywalker",
      "email": "luke@alliance.org"
    }
  }
}

// or if there is an error
// 503 Service Unavailable
// application/json
{
  "errors": [
    {
      "message": "The GraphQL server is under maintenance",
      "extensions": {
        "code": "some-internal-graphql-server-code",
      }
    }
  ]
}

A GraphQL response is indeed formatted in JSON so application/json as a content-type made perfect sense at the time.

Unfortunately, application/json can also be used by non-GraphQL servers… And your typical micro-services infrastructure usually has a bunch of those non-GraphQL servers:

Let’s assume your CDN goes down for some reason and your clients start seeing responses like so:

// 503 Service Unavailable
// application/json
// This is not a valid GraphQL response
{
  "code": "some-internal-cdn-code",
  "message": "The CDN is under maintenance, please try again later."
}

See the problem?

How can the client know whether the body is valid GraphQL response that it can parse or some other error introduced by a network node in the infrastructure?

It can’t.

The best it can do is display a generic error.

The community tried to avoid this case as much as possible. To do so, the typical solution is to always return a 200 OK status code, even if there is an error (because it would be very evil of an intermediate node to modify a successful response).

This solution was an opportunity for some nice memes, interesting GitHub comments and other funny reddit posts:

This is funny and all… Until you have to deal with it in production.

Entering application/graphql-response+json

In 2025, clients supporting the current GraphQL over HTTP draft may now accept application/graphql-response+json as a Content-Type:

POST /graphql HTTP/2
Accept: application/graphql-response+json, application/json
...

If the server supports it, it’ll respond with an application/graphql-response+json body:

HTTP/2 503
Content-Type: application/graphql-response+json

{
  "errors": [
    {
      "message": "The GraphQL server is under maintenance",
      "extensions": {
        "code": "some-internal-graphql-server-code",
      }
    }
  ]
}

Because the Content-Type is now application/graphql-response+json, the frontend can now safely parse the data and errors parts. And have the warm fuzzy feeling that their response is indeed coming from their origin GraphQL server. No more memes!

Because your server can now use relevant HTTP status codes, it can reuse all the existing tooling and internet infrastructure while still allowing your clients to make informed decisions. It’s win-win 🙌

Conclusion

application/graphql-response+json is great.

If you’re not using it already, you should!

If your server/client doesn’t support it, open an issue, it’s high time to fix this issue in 2025 (and find a new source of memes too 😁)!

In a future post, I’ll talk about partial error handling. This is another area where best practices are evolving and where the new year brings a couple welcome improvements.

Stay tuned and happy 2025!


PS: Many thanks to benjie and the GraphQL over HTTP working group for reviewing this post

    Share:
    Back to Blog