# Errors

> The Chatfuel API's error envelope — machine-readable codes in extensions, the DefinedErrorCode family, and the four rules that catch people.

Page: https://sdk.chatfuel.com/docs/reference/chatfuel-api/errors
Markdown: https://sdk.chatfuel.com/docs/reference/chatfuel-api/errors.md

Codes travel in `extensions`, and the HTTP status line is not where you look for them.

```json
{
  "errors": [
    {
      "message": "...",
      "path": ["bot", "conversation"],
      "extensions": { "code": "NotEnoughPermissions", "service": "livechat", "traceId": "..." }
    }
  ]
}
```

## The rules that catch people [#the-rules-that-catch-people]

<Callout type="warn">
  A 401-equivalent arrives inside an HTTP 200. The gateway answers `200` with an `errors[]` that
  carries an `Unauthorized` code from a subgraph, so a client that branches on `res.ok` reads a
  dead token as a successful request with no data. Scan `errors[].extensions.code`, always.
</Callout>

| Rule                                                             | What it means                                                                                                                                                                                                                                                                                                                               |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A relayed subgraph failure hides the real code one level deeper. | The top-level message reads `Failed to fetch from Subgraph 'x'` and carries no useful code; the real entries — code, `traceId` — sit in `extensions.errors[]`. Every code lookup has to walk down one level too. `workspaceCreateBot` is one that answers this way: `TooManyBotsInWorkspace` and `NotEnoughPermissions` both arrive nested. |
| `data` and `errors` can coexist.                                 | Partial data is normal. The envelope is not "one or the other", so decide per view whether a partial render is acceptable rather than treating the presence of `errors` as the absence of data.                                                                                                                                             |
| WhatsApp delivery failures are not GraphQL errors.               | The send mutation succeeds. The failure appears later on the message itself, as `Message.errors[]` — a `MessageError { code, date, originalErrCode, originalErrMessage }` — and reaches you through the `messageUpdated` subscription. Nothing about it ever enters the error envelope.                                                     |

## Where the codes come from [#where-the-codes-come-from]

`DefinedErrorCode` is the schema's own "global enum for errors that must be handled on the
client". It has 285 values: three global ones and the rest per domain.

| Code                   | Meaning                                                                                                                 |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `Unauthorized`         | The token is not valid any more. Rotate it; do not retry.                                                               |
| `NotEnoughPermissions` | The role this token holds on this bot does not allow the operation — or the id is unknown, or belongs to somebody else. |
| `InternalServerError`  | The server failed.                                                                                                      |

The rest are domain-specific — `FileTooBig`, `FileContentTypeNotSupported`, `FileDoesNotExist`,
`TooManyBotsInWorkspace`, `EnabledTriggerIsImmutable`, and so on. Which codes a given mutation can
return is written in that mutation's doc comment in the bundled schema, so the schema file is where
you look one up. The headings those lists appear under are not consistent — see
[the traps](/docs/reference/chatfuel-api/traps).

## The traceId [#the-traceid]

An error's `extensions.traceId` identifies the request inside Chatfuel, so include it when you
report a problem to them. It is subject to the nesting rule above: when the gateway relays a
subgraph failure, the `traceId` is on the nested entry, not the outer one.

## This page is the API's half [#this-page-is-the-apis-half]

Everything above is produced by Chatfuel. The SDK's own proxy and client produce a second family of
codes — a missing session, a bot the caller has no grant for, an unreachable upstream — before a
request ever reaches Chatfuel, or after its answer comes back. Those are on
[the errors reference](/docs/reference/errors).
