# 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](https://spec.graphql.org/October2021/#sec-Errors). In practice here's an example of error you might encounter:

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

{% hint style="info" %}
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](#field-errors).
{% endhint %}

## 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:

<table><thead><tr><th width="187">HTTP Status Code</th><th>Description</th></tr></thead><tbody><tr><td>400</td><td>The request was invalid. This could be because there was:<br>- A syntax error in the request, such as a missing quote or brace.<br>- A schema error in the request, such as a typo in a field name.</td></tr><tr><td>401</td><td>The token in the <code>Authorization</code> header was invalid or expired. See <a href="/pages/zvMuBM7DK8dJgA84rtNv">how to generate a valid token here</a>.</td></tr><tr><td>415</td><td>The content type provided in the HTTP request is invalid. In practice this means you're probably missing the <code>content-type: application/json</code> header.</td></tr><tr><td>429</td><td>Rate limit exceeded. The client has sent too many requests and must wait before being allowed to receive data again.<br>When faced with this error, implement an <code>EXPONENTIAL_BACKOFF</code>. See <a href="#rate-limit">rate limit</a> and <a href="#retry-policy">retry policy</a>.</td></tr><tr><td>500</td><td>There was an unexpected technical error during the execution of the request.</td></tr><tr><td>502</td><td>The GraphQL server is currently unable to process any request.</td></tr><tr><td>504</td><td>The GraphQL server failed to respond in time to the request.</td></tr></tbody></table>

## 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](https://spec.graphql.org/October2021/#sec-Handling-Field-Errors), 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.

{% hint style="info" %}
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.
{% endhint %}

Here's an example of such an error:

```json
{
  "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:

<table><thead><tr><th width="220">Error name</th><th>Description</th></tr></thead><tbody><tr><td><code>INTERNAL_ERROR</code></td><td>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.</td></tr><tr><td><code>INVALID_ARGUMENT</code></td><td>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 <code>message</code> attribute for details.</td></tr><tr><td><code>NOT_FOUND</code></td><td>The resource wasn't found.</td></tr><tr><td><code>PERMISSION_DENIED</code></td><td>The request was successfully authorized, but the permissions of the user aren't sufficient to execute the request.</td></tr><tr><td><code>UNAUTHORIZED</code></td><td>The request failed to be authorized. This is likely caused by an invalid authorization token, such as an expired token.</td></tr></tbody></table>

## 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:

<table><thead><tr><th width="240">Retry Policy</th><th>How to implement it</th></tr></thead><tbody><tr><td><code>null</code> or <code>undefined</code></td><td>Same as <code>NO_RETRY</code></td></tr><tr><td><code>NO_RETRY</code></td><td>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.</td></tr><tr><td><code>RETRY_ONCE</code></td><td>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.<br>When implementing the single retry, be mindful to avoid infinite loops.</td></tr><tr><td><code>EXPONENTIAL_BACKOFF</code></td><td>An <a href="https://en.wikipedia.org/wiki/Exponential_backoff">exponential backoff</a> policy is useful to retry a request a certain amount of time without overwhelming the server.<br>We recommend using the following settings for your exponential backoff:<br>- Max retry count = 10<br>- Multiplicator = 2<br>- Initial wait time = 1s<br>- Max wait time = 10s<br><br>We return this type of retry policy if we encountered a critical hardware issue, or if we've experienced a network failure.</td></tr></tbody></table>

## 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](#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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.iadvize.dev/technologies/graphql-api/error-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
