# Error

> The one body every failing request returns, whatever the status.

Source: https://pokemontcgapi.com/docs/objects/error

There is a single error shape across the whole API. Switch on `error.code`, never on `error.message`: codes are a published contract and do not change once shipped, messages get reworded whenever a rewording helps someone.

`request_id` also travels in the `X-Request-Id` response header, which the API sends on successful responses too. Log it — it is the key into our logs, and the first thing support will ask for.

## Fields

| Field | Type | Null | Description |
| --- | --- | --- | --- |
| `error.code` | string | no | SCREAMING_SNAKE code from the taxonomy. See [errors](https://pokemontcgapi.com/docs/errors). |
| `error.message` | string | no | English sentence for a human reader. Not stable, not for parsing. |
| `error.details` | object | yes | Structured context, and the field worth reading: `position` and `valid_fields` for query errors, `valid_includes` for rejected relations, `supported` for rejected enums, `max` and `requested` for limits. Absent when there is nothing structured to add. |
| `error.request_id` | string | no | UUID for this request. Also in `X-Request-Id`. |

## Example

`error.json`

```json
{
  "error": {
    "code": "INVALID_QUERY",
    "message": "Unknown search field \"nmae\" at position 0. The full list of searchable fields is in details.valid_fields.",
    "details": {
      "field": "nmae",
      "position": 0,
      "valid_fields": ["abilities.name", "abilities.text", "abilities.type", "artist", "attacks.damage"]
    },
    "request_id": "151d3d29-3839-472a-a66b-e7636c0e5701"
  }
}
```

## Every code

This table is the complete list of codes the service can return. It is shorter than the enum in the source, on purpose: a code with no reachable throw site is a branch you would write and never execute.

| Status | Code | Retry? |
| --- | --- | --- |
| 400 | `INVALID_QUERY` | no |
| 400 | `QUERY_TOO_COMPLEX` | no |
| 400 | `QUERY_UNSUPPORTED` | no |
| 400 | `INVALID_CURSOR` | no |
| 400 | `INVALID_SELECT_FIELD` | no |
| 400 | `INVALID_INCLUDE` | no |
| 400 | `INVALID_PARAMETER` | no |
| 400 | `LIMIT_EXCEEDED` | no |
| 401 | `MISSING_API_KEY` | no |
| 401 | `INVALID_API_KEY` | no |
| 404 | `CARD_NOT_FOUND` | no |
| 404 | `SET_NOT_FOUND` | no |
| 404 | `ARTIST_NOT_FOUND` | no |
| 404 | `SEALED_NOT_FOUND` | no |
| 403 | `PLAN_REQUIRED` | no |
| 403 | `UPGRADE_REQUIRED` | no |
| 404 | `ROUTE_NOT_FOUND` | no |
| 413 | `PAYLOAD_TOO_LARGE` | no |
| 415 | `UNSUPPORTED_MEDIA_TYPE` | no |
| 500 | `INTERNAL_ERROR` | yes, with backoff |
| 503 | `FEATURE_NOT_CONFIGURED` | yes, with backoff |
