Error Management

Managing errors is an essential part of the integration with any API. Although we strive to provide a perfectly stable service, it's reasonable to expect technical errors occasionally. In this section we'll list the various error cases you may encounter, and what they mean.

When using our GraphQL API (or any other GraphQL API over HTTP) there are two levels of error to consider: request errors and field errors. But first let's have a look at how a standard GraphQL error is formatted.

Error format

GraphQL errors are standardised, and you can expect our GraphQL API to follow the format of the official GraphQL specification. In practice here's an example of error you might encounter:

{
  "data": null,
  "errors": [
    {
      "message": "Insufficient permissions to perform the operation",
      "extensions" : {
        "name" : "PERMISSION_DENIED",
        "retryPolicy": "NO_RETRY"
      }
    }
  ]
}

Please note that you might find an attribute named code under the extensions object. This attribute is deprecated and should not be used under any circumstances. If you're looking for a stable error identifier, use the name attribute. You can see the most frequent ones below.

Request errors

A request error occurs when a whole request has been dismissed as being impossible to execute. Causes may vary and could be as wide as an invalid request, to our service being temporarily unavailable. Here are the possible request errors:

HTTP Status Code
Description

400

The request was invalid. This could be because there was: - A syntax error in the request, such as a missing quote or brace. - A schema error in the request, such as a typo in a field name.

401

415

The content type provided in the HTTP request is invalid. In practice this means you're probably missing the content-type: application/json header.

429

500

There was an unexpected technical error during the execution of the request.

502

The GraphQL server is currently unable to process any request.

504

The GraphQL server failed to respond in time to the request.

Field errors

A field error occurs when a request was valid but a technical error happened while trying to resolve one of the fields. Causes may vary but the errors will always be listed as part of the response payload. This is described in the official GraphQL specification, and is a behaviour that contrasts with a typical REST API. Indeed, it becomes possible to have a response containing partial data and an error list while returning an HTTP 200 status code.

As a user of a GraphQL API you must therefore always check the errors array in the response to ensure no error would prevent you from accessing the data you need.

Here's an example of such an error:

{
  "data": {
    "conversation": {
      "id": "68eded46-6e63-4603-8849-891dba10bcbe",
      "language": "en",
      "conversions": null
    }
  },
  "errors": [
    {
      "message": "Internal server error",
      "path": [
        "conversation",
        "conversions"
      ],
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "extensions" : {
        "name" : "INTERNAL_ERROR",
        "retryPolicy": "RETRY_ONCE"
      }
    }
  ]
}

As you can see in the error above, our errors contain the extensions object. As per the GraphQL specs, this object is here to add any data that would be relevant to the error. Our API will always contain a unique identifier under the name attribute. This attribute will inform you of the type of error that was encountered. These type of errors are specific to the query or mutation being executed, and will generally be documented on the query or mutation directly, though here's a list of the standard error type you might encounter:

Error name
Description

INTERNAL_ERROR

Our GraphQL encountered a technical error. This error might be temporary (such as hardware failure, network error, etc.) or might be due to a bug that requires fixing on our end.

INVALID_ARGUMENT

One of the arguments of the query or mutation you provided wasn't valid. This could be a type error, parsing error, or another validation. See the message attribute for details.

NOT_FOUND

The resource wasn't found.

PERMISSION_DENIED

The request was successfully authorized, but the permissions of the user aren't sufficient to execute the request.

UNAUTHORIZED

The request failed to be authorized. This is likely caused by an invalid authorization token, such as an expired token.

Retry Policy

When the whole query has failed, or when a partial result is not acceptable for the consumer, it is sometimes possible to retry the request shortly after encountering an error. Not all errors are retriable, for instance an INVALID_ARGUMENT will still be invalid even after retrying.

To simplify the logic implemented on the consumer side, we've set an attribute named retryPolicy which informs the consumer if a retry is possible, and what to do. Bear in mind that when implementing a retry policy, avoiding infinite loops is extremely important. When implementing a retry, please add this header to your HTTP request: x-iAdvize-retry-count that contains the number of attempts for a given request.

Here are the possible values for the retryPolicy attribute, and what to do with it:

Retry Policy
How to implement it

null or undefined

Same as NO_RETRY

NO_RETRY

No retry should be immediately attempted. This category of error is usually due to a consumer implementation error, such as a permission error or an invalid argument.

RETRY_ONCE

Your program can immediately retry the request. This retry policy is attached to errors that are transient, such as networking failure or hardware failure. Retrying may succeed. When implementing the single retry, be mindful to avoid infinite loops.

EXPONENTIAL_BACKOFF

Rate limit

To ensure a good quality of service, we limit how many requests a single client can send to our system. This limit is set above 50 requests per second.

If you were faced with HTTP return codes 429, this would means you've exceeded that rate and you should reduce the rate at which requests are being sent to our systems. You could also implement the EXPONENTIAL_BACKOFF as described in the retry policy section.

Other general good practices

When dealing with errors there are some industry standard practices to put in place, such as logging to help diagnose any issue. A good error log would contain:

  • A timestamp with a timezone

  • The URL that was hit

  • The HTTP request, containing the HTTP verb, the body (such as json), and the headers

  • The HTTP response, containing the HTTP status code, the headers and the body

These are crucial pieces of information allowing anyone to then investigate a potential issue.

Other, more advanced, practices such as gathering metrics about response time an error rates might also be useful.

Last updated